python模块层次结构命名约定
Posted
技术标签:
【中文标题】python模块层次结构命名约定【英文标题】:python modules hierarchy naming convention 【发布时间】:2013-02-20 16:20:18 【问题描述】:我希望有如下的模块/包结构:
/__init__.py
/mymodule.py
/mymodule/
/mymodule/__init__.py
/mymodule/submodule.py
然后使用如下模块:
import mymodule
import mymodule.submodule
但文件“mymodule.py”似乎与“mymodule”目录冲突。
这里的正确命名约定是什么?
【问题讨论】:
【参考方案1】:您正在处理一个package。你应该有的包结构是:
/some-parent-directory # This needs to be on sys.path
/mymodule # This is not really a module - it's a package
__init__.py # import mymodule
# init is loaded when you `import mymodule` or anything below it
some.py # import mymodule.some
implementation.py # import mymodule.implementation
files.py # import mymodule.files
/submodule
__init__.py # import mymodule.submodule
# init is loaded when you `import mymodule.submodule` or anything below it
submodule_impl.py # import mymodule.submodule.submodule_impl
goes.py # import mymodule.submodule.goes
here.py # import mymodule.submodule.here
只要 parent 目录位于 sys.path
上,您就可以毫无问题地调用 import mymodule
或 from mymodule.submodule import something
。
如果您想从包的根级别(即from mymodule import SomeItem
或子包from mymodule.submodule import AnotherItem
)获得某些内容,则可以将其导入到相应的__init__.py
文件中。
例如,假设您希望在submodule_impl.py
模块中定义的类CustomClass
可以直接从submodule
导入。您的 submodule/__init__.py
必须包含以下内容:
from .submodule_impl import CustomClass
然后您就可以直接从submodule
导入CustomClass
(即from mymodule.submodule import CustomClass
)
【讨论】:
我在最后几段中多次看到您的建议,似乎这是将代码移出 __init__.py 的首选方式。我的问题是,我实际上并不希望 submodule_imp 成为公共 API 的一部分。就像,这是一个实现细节。import mymodule.submodule.submodule_imp
在概念上是不可能的。有什么办法可以解决这个问题,还是我不应该担心它只是 Python 的本质,我应该相信库使用者会忽略未记录的内容?
后者 - Python 的理念是“我们都是成年人” - 除非你采取额外的步骤,否则人们无论如何都可以从你的模块中导入随机的东西 - 如果你只记录人们的方式 应该与你的包交互,这通常是人们会做的。【参考方案2】:
如果你想制作一个包,你必须了解 Python 如何将文件名转换为模块名。
文件mymodule.py
将作为mymodule
提供,假设解释器在Python 搜索路径的目录中找到它。如果您使用的是不区分大小写的文件系统,它也可能可以使用不同的大小写导入(但您应该避免使用这种依赖于系统的行为)。
包是一个包含__init__.py
文件的目录。最近有一些动作允许没有这些文件的包,但我将忽略这个答案的不太常见的情况。一个包成为 Python 中的一个模块,其代码来自 __init__.py
文件。所以文件mypackage/__init__.py
可以导入为mypackage
。
__init__.py
文件直接在 Python 搜索路径中没有任何意义(好吧,我想你可以将它导入一个 __init__
模块,但这可能是个坏主意)。
因此,根据您的情况,以下是适当的文件系统布局:
toplevel/
mymodule/
__init__.py # put code here for mymodule
submodule.py # put code here for mymodule.submodule
只有 toplevel
文件夹应该在 Python 搜索路径中。
【讨论】:
我看到 Python 的人不鼓励在mymodule/__init__.py
中放置重要的代码,例如。 Alex Martelli,这似乎与此不一致。 (不是说我一定同意……)
确实如此。更流行的方式是将mymodule
的实际代码放入未记录的子模块中,然后将其公共API 导入__init__.py
。
感谢您提供翔实的回答。遗憾的是,python 需要如此肮脏的 hack 来做一件显而易见的事情。
@SergeyRomanovsky - 我不会称其为 hack - 在您描述的情况下,您必须查看 三个 位置才能查看定义符号的位置(因为from mymodule import something
会查看mymodule.__init__
、mymodule.mymodule
和mymodule.mymodule.__init__
)。 Python 3.3 确实重新访问了包模块并对其进行了重大更新。非常值得研究。
@SeanVieira:您说“Python 3.3 确实重新访问了包模块并对其进行了重大更新。值得研究”?你会详细说明吗?以上是关于python模块层次结构命名约定的主要内容,如果未能解决你的问题,请参考以下文章