有关python导入的最终答案

2024-09-25 04:25:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道对于Python中的相同导入问题有很多问题,但是似乎没有人能够提供正确使用的清晰示例。

假设我们有一个包mypackage,它有两个模块foobar。在foo内部,我们需要能够访问bar

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

我们希望能够:

  • 导入mypackage.foo
  • 作为脚本运行foo.py,并从__main__部分执行示例用法或测试。
  • 使用Python2.5

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

# 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()

Tags: 模块pyimport示例fooinitmaindef
2条回答

我的解决方案看起来更干净一些,并且可以与所有其他导入一起位于顶部:

try:
   from foo import FooClass
except ModuleNotFoundError:
   from .foo import FooClass

查看PEP 328中的以下信息:

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__',因此不能执行相对导入。即使mypackagesys.path上,这也是正确的。基本上,只有在导入模块时,才能从该模块进行相对导入。

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

1)在foo.py中,检查__name__ == '__main__'是否,并有条件地将mypackage添加到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)始终使用from mypackage import bar导入bar,并以自动可见mypackage的方式执行foo.py

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

相关问题 更多 >