Is there a reliable way to get the path of the caller module from a Python function that is executed within a Sphinx conf.py?
<p>I'm running some custom Python code in Sphinx and <strong>need to get the path to the caller module</strong>.  (Essentially this is the caller's <code>__file__</code> object; I need to interpret a filename relative to this location.)</p>

<p>I can get the filename from <code>inspect.stack()</code> as per <a href="http://stackoverflow.com/questions/3711184">How to use inspect to get the caller&#39;s info from callee in Python?</a>, but apparently I need to interpret this filename in the context of the Python startup directory. (Sometimes <code>inspect.stack()[k][1]</code> is an absolute path but sometimes it is a relative path like <code>conf.py</code>; the <a href="https://docs.python.org/2/library/inspect.html#the-interpreter-stack" rel="nofollow"><code>inspect.stack()</code></a> function doesn't seem to document this but <a href="http://stackoverflow.com/a/3711243/44330">unutbu claims in a comment</a> that it is relative to the Python startup directory. )</p>

<p>Sphinx does some unintentionally evil things like this comment:</p>

<pre><code># This file is execfile()d with the current directory set to its
# containing dir.
</code></pre>

<p>so <code>os.path.abspath(filename)</code> doesn't work, and</p>

<pre><code># If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('extensions'))
</code></pre>

<p>so <code>sys.path[0]</code> is corrupted by the time my code gets to it.</p>

<p>How do I find the startup directory in Python, if <code>sys.path</code> has been modified?</p>

<p>Or is there another way to get the path to the caller module?</p>

<hr>

<p>If I run <a href="http://stackoverflow.com/a/39299596/44330">Jean-FranÃ§ois Fabre's answer</a></p>

<pre><code>for file,line,w1,w2 in traceback.extract_stack():
    sys.stdout.write('  File "{}", line {}, in {}\n'.format(file,line,w1))
</code></pre>

<p>I get this:</p>

<pre><code>File "c:\app\python\anaconda\1.6.0\Scripts\sphinx-build-script.py", line 5, in &lt;module&gt;
File "c:\app\python\anaconda\1.6.0\lib\site-packages\Sphinx-1.4.1-py2.7.egg\sphinx\__init__.py", line 51, in main
File "c:\app\python\anaconda\1.6.0\lib\site-packages\Sphinx-1.4.1-py2.7.egg\sphinx\__init__.py", line 92, in build_main
File "c:\app\python\anaconda\1.6.0\lib\site-packages\Sphinx-1.4.1-py2.7.egg\sphinx\cmdline.py", line 243, in main
File "c:\app\python\anaconda\1.6.0\lib\site-packages\Sphinx-1.4.1-py2.7.egg\sphinx\application.py", line 155, in __init__
File "conf.py", line 512, in setup
[more lines elided, the conf.py is the one that matters]
</code></pre>

<p>so the problem is that I need to find the path to <code>conf.py</code> but the current directory has been changed by Sphinx so I can't just do <code>os.path.abspath(caller_filename)</code></p>

<p>Bah, I'm just going to get around the issue by allowing callers to pass in their <code>__file__</code> value  :-(</p>

<p>my function:</p>

<pre><code>def do_something(app, filename, relroot=None):
   if relroot is None:
      relroot = '.'
   else:
      relroot = os.path.dirname(relroot)
   path = os.path.join(relroot, filename)
   ...
</code></pre>

<p>in conf.py:</p>

<pre><code>def setup(app):
   mymodule.do_something(app, 'path/to/file', relroot=__file__)
</code></pre>

python python-sphinx