Google Python 风格指南和相关导入
Google Python Style Guide & relative imports
Google Python 风格指南 says:
Do not use relative names in imports. Even if the module is in the same package, use the full package name. This helps prevent unintentionally importing a package twice.
导致两次导入包的示例设置是什么?
这是对 隐式相对导入 的 Python 2 行为 (deprecated since 2.6) 的引用:允许 import bar
在一个包 foo
来引用模块 foo.bar
。考虑 sys.path
上的一个目录,它看起来像
…
|-- client.py
`-- pkg
|-- __init__.py
|-- mod.py
`-- script.py
具有以下内容的文件:
client.py
print "client..."
from pkg import mod,script
print "client!"
pkg/__init__.py
print "pkg"
pkg/mod.py
print "mod: %r"%__name__
pkg/script.py
print "script:",__name__,__package__
if __name__=='__main__':
import mod,client
print "script!"
在此设置中 mod
可以轻松导入两次:
$ PYTHONPATH=… python …/pkg/script.py
script: __main__ None
mod: 'mod'
client...
pkg
mod: 'pkg.mod'
script: pkg.script None
client!
script!
为了减少配置开销,Python 将目录 pkg
添加到 sys.path
,有效地假定 script.py
是顶级模块 script
.不幸的是,这意味着 import mod
创建了一个名为 mod
的 顶级 模块,而 pkg.mod
的显式导入稍后会导致它的另一个副本以其全名存在(仅在导入 pkg
本身之后)。
recognized that this poses a problem, and later -m
was adjusted 告诉正在执行的模块关于在其中找到它的包,以便相对导入(隐式或显式)正常工作:
$ PYTHONPATH=… python -m pkg.script
pkg
script: __main__ pkg
mod: 'pkg.mod'
client...
script: pkg.script None
client!
script!
请注意,pkg
现在首先导入(由 -m
本身!),script
现在立即具有 __package__
属性,并且 mod
只导入一次。当然, script
本身 被(仍然)加载了两次,因为它的名字第一次被 __main__
替换,所以 from pkg import script
可以在下面找到它一个不同的名字。
道德 是,根据 __name__=='__main__'
实现“模块也可以是脚本”从根本上被打破了(和替换 have been rejected):一个模块已经 有 一个 __name__
,并且创建一个单独的模块对象作为入口点以便它的 __name__
可以不同就像复制 Java class(及其所有静态数据)提供 main
。制作一个没有人导入的模块有效,但却是矛盾的(并且破坏了导入包的所有成员的代码检查)。
Google Python 风格指南 says:
Do not use relative names in imports. Even if the module is in the same package, use the full package name. This helps prevent unintentionally importing a package twice.
导致两次导入包的示例设置是什么?
这是对 隐式相对导入 的 Python 2 行为 (deprecated since 2.6) 的引用:允许 import bar
在一个包 foo
来引用模块 foo.bar
。考虑 sys.path
上的一个目录,它看起来像
…
|-- client.py
`-- pkg
|-- __init__.py
|-- mod.py
`-- script.py
具有以下内容的文件:
client.py
print "client..."
from pkg import mod,script
print "client!"
pkg/__init__.py
print "pkg"
pkg/mod.py
print "mod: %r"%__name__
pkg/script.py
print "script:",__name__,__package__
if __name__=='__main__':
import mod,client
print "script!"
在此设置中 mod
可以轻松导入两次:
$ PYTHONPATH=… python …/pkg/script.py
script: __main__ None
mod: 'mod'
client...
pkg
mod: 'pkg.mod'
script: pkg.script None
client!
script!
为了减少配置开销,Python 将目录 pkg
添加到 sys.path
,有效地假定 script.py
是顶级模块 script
.不幸的是,这意味着 import mod
创建了一个名为 mod
的 顶级 模块,而 pkg.mod
的显式导入稍后会导致它的另一个副本以其全名存在(仅在导入 pkg
本身之后)。
recognized that this poses a problem, and later -m
was adjusted 告诉正在执行的模块关于在其中找到它的包,以便相对导入(隐式或显式)正常工作:
$ PYTHONPATH=… python -m pkg.script
pkg
script: __main__ pkg
mod: 'pkg.mod'
client...
script: pkg.script None
client!
script!
请注意,pkg
现在首先导入(由 -m
本身!),script
现在立即具有 __package__
属性,并且 mod
只导入一次。当然, script
本身 被(仍然)加载了两次,因为它的名字第一次被 __main__
替换,所以 from pkg import script
可以在下面找到它一个不同的名字。
道德 是,根据 __name__=='__main__'
实现“模块也可以是脚本”从根本上被打破了(和替换 have been rejected):一个模块已经 有 一个 __name__
,并且创建一个单独的模块对象作为入口点以便它的 __name__
可以不同就像复制 Java class(及其所有静态数据)提供 main
。制作一个没有人导入的模块有效,但却是矛盾的(并且破坏了导入包的所有成员的代码检查)。