相对python导入的最终答案 [英] Ultimate answer to relative python imports

查看:101
本文介绍了相对python导入的最终答案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道Python中存在很多关于相同导入问题的问题,但似乎没有人设法提供正确使用的明确示例。

I know that there are lots of questions about the same import issues in Python but it seems that nobody managed to provide a clear example of correct usage.

让我们说我们有一个包 mypackage ,包含两个模块 foo bar 。在 foo 里面我们需要能够访问 bar

Let's say that we have a package mypackage with two modules foo and bar. Inside foo we need to be able to access bar.

因为我们还在开发它, mypackage 不在 sys.path 中。

Because we are still developing it, mypackage is not in sys.path.

我们希望能够:


  • import mypackage.foo

  • 运行 foo.py 作为脚本并执行示例用法或测试 __ main __ 部分。

  • 使用Python 2.5

  • import mypackage.foo
  • run foo.py as a script and execute the sample usage or tests from the __main__ section.
  • use Python 2.5

我们如何在foo.py中进行导入,以确保它在所有这些情况下都能正常工作。

How do we have to do the import in foo.py in order to be sure it will work in all these cases.

# mypackage/__init__.py
...

# mypackage/foo/__init__.py
...

# mypackage/bar.py  
def doBar()
    print("doBar")

# mypackage/foo/foo.py
import bar # fails with module not found
import .bar #fails due to ValueError: Attempted relative import in non-package

def doFoo():
    print(doBar())

if __name__ == '__main__':
    doFoo()


推荐答案

查看 PEP 328


相对导入使用模块的 __ name __ 属性,用于确定模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,它设置为'__ main __'),则解析相对导入,就像模块是顶级模块一样,无论模块实际位于文件系统上的位置。

Relative imports use a module's __name__ attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to '__main__') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.

当你运行 foo.py 作为脚本,该模块的 __ name __ '__ main __',因此您无法进行相对导入。即使 mypackage sys.path 上,也是如此。基本上,如果导入该模块,您只能从模块进行相对导入。

When you run foo.py as a script, that module's __name__ is '__main__', so you cannot do relative imports. This would be true even if mypackage was on sys.path. Basically, you can only do relative imports from a module if that module was imported.

以下是解决此问题的几个选项:

Here are a couple of options for working around this:

1)在 foo.py 中,检查 __ name__ =='__ main __'和有条件地将 mypackage 添加到 sys.path

1) In foo.py, check if __name__ == '__main__' and conditionally add mypackage to sys.path:

if __name__ == '__main__':
    import os, sys
    # get an absolute path to the directory that contains mypackage
    foo_dir = os.path.dirname(os.path.join(os.getcwd(), __file__))
    sys.path.append(os.path.normpath(os.path.join(foo_dir, '..', '..')))
    from mypackage import bar
else:
    from .. import bar

2)始终从mypackage导入栏使用导入 bar ,然后执行 foo .py 以这种方式自动显示 mypackage

2) Always import bar using from mypackage import bar, and execute foo.py in such a way that mypackage is visible automatically:

$ cd <path containing mypackage>
$ python -m mypackage.foo.foo

这篇关于相对python导入的最终答案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆