0

我正在寻找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

我正在尝试构建一种确定的方法来确定模块正在从哪个文件执行。因为我使用 IPython 作为 shell,所以我实际上可能会遇到这种情况。

用法示例:
我正在处理的项目有两个版本,我在调试它们的过程中比较它们的行为。..假设他们在目录'proj1''proj2'. ..foo我又在 IPython 解释器中加载了哪些内容?

理想:

In [242]: from my_tools import loc
In [243]: loc(foo)
'/home/blah/projects/proj2/foo.py'

** 正如 abarnert 指出的那样,这是不可能的,因为 python 不记录相对导入的基本目录位置。但是,这将适用于正常(非相对)导入。

** 此外,常规 python(相对于 IPython)不允许从当前目录导入,而只能从模块目录导入。

4

2 回答 2

1

该信息不再可用,期间。Tracebacks、调试器、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__)不是你所希望的,但我想不出更好的了。


如果你想变得棘手,你可以构建一个导入钩子,在导入模块时修改它们,添加一个新__abspath__属性,或者更简单地说,更改__file__为始终是一个 abspath。importlib使用Python 3.1+ 模块更容易。

作为概念的快速证明,我一起拍了拍abspathimporter。执行完 .py 之后import imppath,您每进一步import找到一个正常的 .py 文件或包,都会删除其 .py 文件或包__file__

我不知道它是否适用于 .so/.pyd 模块或没有源代码的 .pyc 模块。它绝对不适用于 zipfile 中的模块、冻结模块或任何其他不使用 stock 的模块FileFinder。它不会追溯影响之前导入的任何内容的路径。它需要 3.3+,而且非常脆弱(最严重的是,FileFinder类或其钩子函数必须是最后一件事sys.path_hooks——在我测试的四个 Mac 和 linux 机器上的 CPython 3.3.0-3.3.1 中默认情况下它是,但当然不能保证)。

但它显示了如果你愿意,你可以做什么。老实说,过去 20 分钟左右在 iPython 中玩耍,这很方便。

于 2013-05-06T22:42:54.277 回答
0
import os
import foo

foodir = os.getcwd()

os.chdir('/other/location')

foodir现在已将原始目录存储在其中...

于 2013-05-06T22:34:09.963 回答