当我开发一个纯Python 2的包时,我可以使用简单的
添加Python 3支持后,我必须转移到新的相对导入语法,这也被2.7支持:
一个解决方法是通过从上级目录导入它作为模块来调用文件:
然而,这会对工作目录提出要求,这将阻止您将输出导管到其他同样关注工作目录的程序中。有没有办法两全其美?即在Python 2和3中支持脚本运行和作为包的一部分导入,同时在两者中正常工作?
下面的评论提到根据PEP 366设置
import b
语法来导入相对路径,而不必关心导入文件是否在包内。这样做的好处是,我可以通过执行文件来运行任何文件中的if __name__ == "__main__":
块,并且所有的导入都能正常工作。添加Python 3支持后,我必须转移到新的相对导入语法,这也被2.7支持:
from . import b
。然而,这种语法仅在包内起作用。直接执行文件将不再起作用:Traceback (most recent call last):
File "./a.py", line 2, in <module>
from . import b
ValueError: Attempted relative import in non-package
一个解决方法是通过从上级目录导入它作为模块来调用文件:
python -m foo.a
然而,这会对工作目录提出要求,这将阻止您将输出导管到其他同样关注工作目录的程序中。有没有办法两全其美?即在Python 2和3中支持脚本运行和作为包的一部分导入,同时在两者中正常工作?
示例包结构:
foo/
foo/__init__.py
foo/a.py (imports b)
foo/b.py (imports c)
foo/c.py
我希望以下两种情况都能适用于x在(a, b, c)范围内:
import foo.x (in some file when foo/ is in path)
python[23] path/to/foo/x.py
下面的评论提到根据PEP 366设置
__package__
,但是"如果脚本被移动到不同的包或子包中,则需要手动更新样板文件。"
更新:我尝试让PEP 366解决方案起作用,但无法理解。它说:
这是从未导入的包中执行文件时的情况。那么这个额外的代码会是什么样子?需要额外的代码来操作
sys.path
,以便在顶级包不可导入的情况下使直接执行工作。
__package__
可能会有帮助。 - user2357112__package__
。 - otus__package__
是你正在寻找的解决方案,但我不理解你关于尝试它的编辑。你不仅希望import foo.x
能够工作,而且即使你将foo
重命名为其他名称,它也可以自动工作?如果你更改包名称,显然你必须更改导入。一般来说,导入只能与sys.path
上的模块/包一起使用。如果你想要伪造它,以便导入不在sys.path
上的内容,你需要在程序内修改sys.path
,以便脚本将其包目录添加到路径中。 - BrenBarn