有没有一种可靠的方法可以从在 Sphinx conf.py 中执行的 Python 函数中获取调用者模块的路径?
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?
我运行正在 Sphinx 中编写一些自定义 Python 代码,需要获取调用方模块的路径。 (本质上这是调用者的 __file__
对象;我需要解释一个相对于此位置的文件名。)
我可以根据 How to use inspect to get the caller's info from callee in Python?, but apparently I need to interpret this filename in the context of the Python startup directory. (Sometimes inspect.stack()[k][1]
is an absolute path but sometimes it is a relative path like conf.py
; the inspect.stack()
function doesn't seem to document this but unutbu claims in a comment 从 inspect.stack()
获取文件名,它是相对于 Python 启动目录的。 )
Sphinx 做了一些无意中的坏事,就像这个评论:
# This file is execfile()d with the current directory set to its
# containing dir.
所以 os.path.abspath(filename)
不起作用,并且
# 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'))
所以 sys.path[0]
在我的代码到达它时已损坏。
如果sys.path
被修改,如何在Python中找到启动目录?
或者有其他方法获取调用模块的路径吗?
如果我运行
for file,line,w1,w2 in traceback.extract_stack():
sys.stdout.write(' File "{}", line {}, in {}\n'.format(file,line,w1))
我明白了:
File "c:\app\python\anaconda.6.0\Scripts\sphinx-build-script.py", line 5, in <module>
File "c:\app\python\anaconda.6.0\lib\site-packages\Sphinx-1.4.1-py2.7.egg\sphinx\__init__.py", line 51, in main
File "c:\app\python\anaconda.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.6.0\lib\site-packages\Sphinx-1.4.1-py2.7.egg\sphinx\cmdline.py", line 243, in main
File "c:\app\python\anaconda.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]
所以问题是我需要找到 conf.py
的路径,但当前目录已被 Sphinx 更改,所以我不能只做 os.path.abspath(caller_filename)
您可以使用 traceback
模块获得您想要的。我在 PyScripter 中编写了这个示例代码:
import traceback,sys
def demo():
for file,line,w1,w2 in traceback.extract_stack():
sys.stdout.write(' File "{}", line {}, in {}\n'.format(file,line,w1))
def foo():
demo()
foo()
在我的 Windows PC 运行 PyScripter 上给出:
File "C:\Users\dartypc\AppData\Roaming\PyScripter\remserver.py", line 63, in <module>
File "C:\Users\dartypc\AppData\Roaming\PyScripter\remserver.py", line 60, in main
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\utils\server.py", line 227, in start
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\utils\server.py", line 139, in accept
File "C:\Users\dartypc\AppData\Roaming\PyScripter\remserver.py", line 14, in _accept_method
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\utils\server.py", line 191, in _serve_client
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 391, in serve_all
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 382, in serve
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 350, in _dispatch
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 298, in _dispatch_request
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 528, in _handle_call
File "<string>", line 420, in run_nodebug
File "C:\DATA\jff\data\python\Whosebug\simple_traceback.py", line 10, in <module>
File "C:\DATA\jff\data\python\Whosebug\simple_traceback.py", line 8, in foo
File "C:\DATA\jff\data\python\Whosebug\simple_traceback.py", line 4, in demo
呸,我只是想通过允许调用者传递他们的 __file__
值来解决这个问题:-(
我的函数:
def do_something(app, filename, relroot=None):
if relroot is None:
relroot = '.'
else:
relroot = os.path.dirname(relroot)
path = os.path.join(relroot, filename)
...
在conf.py中:
def setup(app):
mymodule.do_something(app, 'path/to/file', relroot=__file__)
我运行正在 Sphinx 中编写一些自定义 Python 代码,需要获取调用方模块的路径。 (本质上这是调用者的 __file__
对象;我需要解释一个相对于此位置的文件名。)
我可以根据 How to use inspect to get the caller's info from callee in Python?, but apparently I need to interpret this filename in the context of the Python startup directory. (Sometimes inspect.stack()[k][1]
is an absolute path but sometimes it is a relative path like conf.py
; the inspect.stack()
function doesn't seem to document this but unutbu claims in a comment 从 inspect.stack()
获取文件名,它是相对于 Python 启动目录的。 )
Sphinx 做了一些无意中的坏事,就像这个评论:
# This file is execfile()d with the current directory set to its
# containing dir.
所以 os.path.abspath(filename)
不起作用,并且
# 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'))
所以 sys.path[0]
在我的代码到达它时已损坏。
如果sys.path
被修改,如何在Python中找到启动目录?
或者有其他方法获取调用模块的路径吗?
如果我运行
for file,line,w1,w2 in traceback.extract_stack():
sys.stdout.write(' File "{}", line {}, in {}\n'.format(file,line,w1))
我明白了:
File "c:\app\python\anaconda.6.0\Scripts\sphinx-build-script.py", line 5, in <module>
File "c:\app\python\anaconda.6.0\lib\site-packages\Sphinx-1.4.1-py2.7.egg\sphinx\__init__.py", line 51, in main
File "c:\app\python\anaconda.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.6.0\lib\site-packages\Sphinx-1.4.1-py2.7.egg\sphinx\cmdline.py", line 243, in main
File "c:\app\python\anaconda.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]
所以问题是我需要找到 conf.py
的路径,但当前目录已被 Sphinx 更改,所以我不能只做 os.path.abspath(caller_filename)
您可以使用 traceback
模块获得您想要的。我在 PyScripter 中编写了这个示例代码:
import traceback,sys
def demo():
for file,line,w1,w2 in traceback.extract_stack():
sys.stdout.write(' File "{}", line {}, in {}\n'.format(file,line,w1))
def foo():
demo()
foo()
在我的 Windows PC 运行 PyScripter 上给出:
File "C:\Users\dartypc\AppData\Roaming\PyScripter\remserver.py", line 63, in <module>
File "C:\Users\dartypc\AppData\Roaming\PyScripter\remserver.py", line 60, in main
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\utils\server.py", line 227, in start
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\utils\server.py", line 139, in accept
File "C:\Users\dartypc\AppData\Roaming\PyScripter\remserver.py", line 14, in _accept_method
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\utils\server.py", line 191, in _serve_client
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 391, in serve_all
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 382, in serve
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 350, in _dispatch
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 298, in _dispatch_request
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 528, in _handle_call
File "<string>", line 420, in run_nodebug
File "C:\DATA\jff\data\python\Whosebug\simple_traceback.py", line 10, in <module>
File "C:\DATA\jff\data\python\Whosebug\simple_traceback.py", line 8, in foo
File "C:\DATA\jff\data\python\Whosebug\simple_traceback.py", line 4, in demo
呸,我只是想通过允许调用者传递他们的 __file__
值来解决这个问题:-(
我的函数:
def do_something(app, filename, relroot=None):
if relroot is None:
relroot = '.'
else:
relroot = os.path.dirname(relroot)
path = os.path.join(relroot, filename)
...
在conf.py中:
def setup(app):
mymodule.do_something(app, 'path/to/file', relroot=__file__)