我希望在调用os.chdir
之后获取模块的路径。
在这个例子中:
import os
os.chdir('/some/location')
import foo # foo is located in the current directory.
os.chdir('/other/location')
# How do I get the path of foo now? ..is this impossible?
.. foo.__file__
变量将'foo.py'
,inspect.stack()[0][1]
也是如此 - 但是,现在无法知道'foo.py'
的位置,对吧?
我可以使用'foo'
在foo
之外(或在内部,而不是将其存储为导入时的变量),这可以让我发现'proj1'
的位置?
我正在尝试构建一个确定的方法来确定模块正在执行哪个文件。由于我使用IPython作为shell,这是我可以实际遇到的。
用法示例:
我正在研究一个项目的两个版本,我正在调试它们在调试过程中的行为。 ..let说他们在目录'proj2'
和foo
。 ..which In [242]: from my_tools import loc
In [243]: loc(foo)
'/home/blah/projects/proj2/foo.py'
我已经在IPython解释器中再次加载了吗?
理想:
{{1}}
**正如abarnert所说,这是不可能的,因为python不记录相对导入的基本目录位置。但是,这将适用于正常(非相对)导入。
**另外,常规python(与IPython相反)不允许从当前目录导入,而只允许从模块目录导入。
答案 0 :(得分:1)
此信息暂不可用。回溯,调试器,ipython魔术等等都无法实现。例如:
# foo.py
def bar():
1/0
$ ipython
In [1]: import foo
In [2]: os.chdir('/tmp')
In [3]: foo.baz()
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-5-a70d319d0d05> in <module>()
----> 1 foo.baz()
/private/tmp/foo.pyc in baz()
ZeroDivisionError: integer division or modulo by zero
所以:
foo.__file__
变量将'foo.py'
,inspect.stack()[0][1]
也是如此 - 但是,现在无法知道'foo.py'
的位置,对吧?
右。正如您所看到的,Python将其视为相对路径,并且只要需要绝对路径,就会根据当前工作目录(错误地)将其解析。
我可以在'foo'之外(或在内部,而不是在导入时将其存储为变量)使用,这将允许我发现foo的位置?
无。你必须把它存放在某个地方。
显而易见的事情是在导入时从外部存储os.path.abspath(foo.__file__)
,或从内部存储os.path.abspath(__file__)
。不是你所希望的,但我想不出更好的东西。
如果您想变得棘手,可以构建import hook,在导入模块时修改模块,添加新的__abspath__
属性,或者更简单地将__file__
更改为始终是一个绝望。使用importlib
模块Python 3.1 +。
作为一个概念的快速证明,我一起拍了abspathimporter
。执行import imppath
之后,每执行一次import
,您就会发现正常的.py文件或包会使其__file__
无效。
我不知道它是否适用于.so / .pyd模块,或者没有源代码的.pyc模块。它绝对不适用于zipfiles,冻结模块或其他任何不使用库存FileFinder
的模块。它不会追溯性地影响在它之前导入的任何内容的路径。它需要3.3+,并且非常脆弱(最严重的是,FileFinder
类或其钩子函数必须是sys.path_hooks
中的最后一个 - 它在CPython 3.3.0-3.3中是默认的。在我测试的四个Mac和Linux机箱上有1个,但肯定不能保证。)
但它显示了如果你愿意你可以做什么。老实说,在过去20分钟左右的时间里,在iPython中玩耍,这很方便。
答案 1 :(得分:0)
import os
import foo
foodir = os.getcwd()
os.chdir('/other/location')
foodir
现在已经存储了原始目录...