python模块和python包有什么区别?
另请参见:"package"和"module"(其他语言)之间的区别是什么?
- 我可能错了,但对我来说:模块基本上是一个python文件。包是一个文件夹,其中包含一组模块(python文件)。
- 要被视为包,该文件夹必须包含一个__init__.py文件。
- @LC2817:这是最常见的情况,但不需要从文件系统加载模块,例如,参见from plumbum.cmd import ls实现。
- @Giuliopincastelli:在python 3.3+中,命名空间包不使用__init__.py。
- 社区如何区分python包和用于分发pypi/wheels/etc等python组件的包?这两个词对我来说似乎是"包裹"这个词的不同应用。
任何python文件都是一个模块,其名称是没有.py扩展名的文件的基名称。包是python模块的集合:当模块是单个python文件时,包是包含额外__init__.py文件的python模块的目录,用于区分包与刚好包含一组python脚本的目录。包可以嵌套到任何深度,前提是相应的目录包含自己的__init__.py文件。
模块和包之间的区别似乎仅限于文件系统级别。导入模块或包时,python创建的相应对象始终为module类型。但是,请注意,导入包时,只有该包的__init__.py文件中的变量/函数/类是直接可见的,而不是子包或模块。例如,考虑python标准库中的xml包:它的xml目录包含一个__init__.py文件和四个子目录;子目录etree包含一个__init__.py文件,以及一个ElementTree.py文件。查看当您尝试以交互方式导入包/模块时会发生什么:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| >>> import xml
>>> type(xml)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'etree'
>>> import xml.etree
>>> type(xml.etree)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ElementTree'
>>> import xml.etree.ElementTree
>>> type(xml.etree.ElementTree)
<type 'module'>
>>> xml.etree.ElementTree.parse
<function parse at 0x00B135B0> |
在python中,也有一些内置模块,如sys,它们是用C语言编写的,但我认为您不打算考虑您所讨论的那些模块。
- 没有爱的功能,但是更好的解释;)。< 3
- 感谢您明确指出,python创建的相应对象始终是module类型。我正在编写一个调试器,我担心我的调试器说我的包是module的错误。
- @你真是个无爱的人。
- "任何python文件都是一个模块"不是一个有用的描述。包含破折号的python文件,如function-of-love.py,无法导入,我不会调用它们模块。对于不同的脚本文件,如function-of-love.py,它是一个有用的设计模式,这些脚本文件不能从可以导入的模块文件(如function_of_love.py)中导入。
- @带有包含破折号的文件名的jolvi python文件仍然可以作为模块导入,只是不能用通常的import语句导入,因为在python标识符中不允许使用破折号。用importlib.import_module()代替。
- @朱利奥皮安卡斯泰利,你是说使用破折号作为模块名是合理的习惯吗?
- @我不是乔维。你在我的评论里读到了什么?我只是说,如果您碰巧遇到一个名为破折号的python文件,您仍然可以将其作为模块导入。我没有对命名python文件的首选方法做任何声明。我相信你可以在其他地方找到它:通常强烈建议避免使用破折号而使用下划线。
- @Giuliopincastelli您同意在不打算导入的python文件的文件名中使用破折号是一种常见的命名约定吗?我很乐意把我上面的评论从"不能"改为"不应该"。
- @我从未听说过这样的约定。
- 感谢您帮助我使用xml.etree。
- 由于对python不熟悉,在导入父包时,子包或模块在默认情况下不可用,这让我很困惑。有什么特别的原因吗?在导入父包时,是否有一个通用的模式,如何使子包或模块可用(通过它们的完全限定名)?
- @sschuberth只在父包的init.py中导入子包。
- @安娜,但那只有当我控制了父包,而不是第三方包时才有效,对吗?
- @当然可以。但是,第三方包作者可能会在其包中包含这样的导入。(我指的当然是__init__.py。)
模块是在一次导入下导入并使用的单个文件(或多个文件)。例如
包是目录中提供包层次结构的模块集合。
1
| from my_package.timing.danger.internets import function_of_love |
模块文档
软件包简介
- 当你说:"一个模块是在一次导入下导入的一个或多个文件"时,你能解释一个模块是多个文件的情况吗?还是我误解了你的意思?
- 当包文件夹名称包含一个或多个句点时会发生什么?
- 根据文档,模块是单个文件。它没有说多个文件可以是一个模块。
- 您不需要文件来创建模块,例如,您可以从zip文件导入模块。包装也一样。在Python中,模块/包只有一个类。包只是一个具有__path__属性的模块。
- @oldgeezer:那么它不能是包,因为名称必须是有效的python标识符。这同样适用于除字母、数字和下划线之外的任何其他字符。
- 软件包也是模块。它们的打包方式不同;它们是由目录加上__init__.py文件组合而成的。它们是可以包含其他模块的模块。
- 根据PEP8,不鼓励在包命名时使用下划线。
- @MartijnPieers您是否有一个链接来支持包也是模块?我同意Mareofraft和模块是单个文件的文档。你的话,即使是真的,也只会增加混乱
- @当然,请参阅参考文档中的导入系统:务必记住,所有包都是模块。
- @雅克:"package"术语表:可以包含子模块或递归子包的python模块。从技术上讲,包是具有__path__属性的python模块。
- @雅克:只有一个文件,__init__.py子模块是包目录中的独立文件(包括更多的包)。
从python词汇表中:
It’s important to keep in mind that all packages are modules, but not all modules are packages. Or put another way, packages are just a special kind of module. Specifically, any module that contains a __path__ attribute is considered a package.
名称中带有破折号的python文件,如my-file.py,不能用简单的import语句导入。代码方面,import my-file与import my - file相同,这将引发异常。这样的文件更好地被描述为脚本,而可导入的文件则是模块。
首先,请记住,在其精确定义中,模块是Python解释器内存中的对象,通常是通过从磁盘读取一个或多个文件而创建的。虽然我们可以非正式地将磁盘文件(如a/b/c.py称为"模块"),但在它与来自其他几个来源(如sys.path的信息组合以创建模块对象之前,它实际上不会成为一个文件。(例如,请注意,根据sys.path和其他设置,可以从同一文件加载两个具有不同名称的模块。)
包是一个可能有子模块(包括子包)的模块。并非所有模块都能做到这一点。例如,创建一个小的模块层次结构:
1 2
| $ mkdir -p a/b
$ touch a/b/c.py |
确保a下没有其他文件。启动python 3.4或更高版本的解释器(例如,使用python3 -i)并检查以下语句的结果:
1 2 3 4 5 6
| import a
a ? <module 'a' (namespace)>
a.b ? AttributeError: module 'a' has no attribute 'b'
import a.b.c
a.b ? <module 'a.b' (namespace)>
a.b.c ? <module 'a.b.c' from '/home/cjs/a/b/c.py'> |
模块a和a.b是包(实际上,一种称为"名称空间包"的包,尽管我们在这里不担心)。但是,模块a.b.c不是一个包。我们可以通过在上面的目录结构中添加另一个文件a/b.py并启动一个新的解释器来证明这一点:
1 2 3 4 5 6 7
| import a.b.c
? ImportError: No module named 'a.b.c'; 'a.b' is not a package
import a.b
a ? <module 'a' (namespace)>
a.__path__ ? _NamespacePath(['/.../a'])
a.b ? <module 'a.b' from '/home/cjs/tmp/a/b.py'>
a.b.__path__ ? AttributeError: 'module' object has no attribute '__path__' |
python确保在加载子模块之前加载所有父模块。上面发现a/是一个目录,因此创建了一个名称空间包a,a/b.py是一个python源文件,它加载并用于创建(非包)模块a.b。此时,您不能有一个模块a.b.c,因为a.b不是一个包,因此不能有子模块。
您还可以看到包模块a具有__path__属性(包必须具有此属性),但非包模块a.b没有。
一个迟来的答案,还有另一个定义:
A package is represented by an imported top-entity which could either
be a self-contained module, or the __init__.py special module as the
top-entity from a set of modules within a sub directory structure.
因此,从物理上讲,包是一个分发单元,它提供一个或多个模块。
- 我觉得在python中有两个包定义,它们是不同的。你的回答似乎把它们结合在一起了。严格地说,python包是一个目录,里面有一个__init__.py模块,但是如果您谈论的是分发单元(通常通过pypi),那么这完全是另一种类型的包(通常由setup.py的存在来定义)。我发现术语package的这两个用法令人困惑,我已经和一些Python初学者谈过了,他们觉得这完全令人困惑。
所以你记得回到你的课本上,在内容页上,章节被划分成模块。因此,存在着不同的概念,不同的章节有相同的目标或部分相同的理论,然后这些部分聚集在一起,被称为模块。同样,在编程中,当不同的函数聚集在一起时,它们被分开并命名为模块。