在Python中,可以在chdir调用之前和之后获取导入的相对导入的路径吗?

时间:2013-05-06 22:30:25

标签: python ipython

我希望在调用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相反)不允许从当前目录导入,而只允许从模块目录导入。

2 个答案:

答案 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现在已经存储了原始目录...