title: xlwings: how to detect whether a python function is being called from VBA module?
body: <h2>Situation</h2>
  
  <p>The <em>xlwings</em> package provides a convenient way to <a href="https://docs.xlwings.org/en/stable/vba.html#run-python" rel="nofollow noreferrer">call python functions from an excel VBA module</a>. The <em>xlwings</em> documentation gives the following basic example:</p>
  
  <blockquote>
    <p>Write the code below into a VBA module.</p>
  
  <pre><code>Sub HelloWorld()
      RunPython ("import hello; hello.world()")
  End Sub
  </code></pre>
    
    <p>This calls the following code in <code>hello.py</code>:</p>
  
  <pre><code># hello.py
  import numpy as np
  import xlwings as xw
  
  def world():
      wb = xw.Book.caller()
      wb.sheets[0].range('A1').value = 'Hello World!'
  </code></pre>
  </blockquote>
  
  <p>Trying to run the python function <code>world()</code> directly (instead of calling it from excel VBA) gives the following error message:</p>
  
  <blockquote>
    <p>Exception: Book.caller() must not be called directly. Call through
    Excel or set a mock caller first with Book.set_mock_caller().</p>
  </blockquote>
  
  <h2>Question</h2>
  
  <p>I would like to modify the <code>world()</code> function such that it raises a custom exception instead when being run directly. In order to achieve this I first need to determine programmatically whether the <code>world()</code> function is being run directly or being called from excel VBA (at least that's what I'd think). How could I do this?</p>