Python模块和Python包之间有什么区别?
另请参阅:“包”和“模块”之间的区别(对于其他语言)
Python模块和Python包之间有什么区别?
另请参阅:“包”和“模块”之间的区别(对于其他语言)
当前回答
任何Python文件都是一个模块,其名称是文件的基本名称,不带.py扩展名。包是Python模块的集合:虽然模块是单个Python文件,但包是包含额外__init__.py文件的Python模块目录,以区分包和恰好包含一堆Python脚本的目录。只要相应的目录包含自己的__init__.py文件,包可以嵌套到任何深度。
模块和包之间的区别似乎只在文件系统级别上存在。当您导入模块或包时,Python创建的相应对象总是模块类型。但是,请注意,当您导入包时,只有该包的__init__.py文件中的变量/函数/类是直接可见的,而不是子包或模块。例如,考虑Python标准库中的xml包:其xml目录包含__init__.py文件和四个子目录;子目录etree包含__init__.py文件,以及ElementTree.py文件。查看尝试以交互方式导入包/模块时发生的情况:
>>> 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编写的,但我不认为您打算在问题中考虑这些模块。
其他回答
首先,请记住,在其精确定义中,模块是Python解释器内存中的一个对象,通常通过从磁盘读取一个或多个文件来创建。虽然我们可以非正式地将磁盘文件(如a/b/c.py)称为“模块”,但在它与其他几个源(如sys.path)的信息结合起来创建模块对象之前,它实际上并不是一个模块。
(例如,请注意,根据sys.path和其他设置,可以从同一个文件加载两个不同名称的模块。这正是python-m my.module在解释器中后跟import my.module时所发生的情况;将有两个模块对象__main__和my.modules,它们都是从磁盘上的同一文件my/module.py创建的。)
包是可能具有子模块(包括子包)的模块。并非所有模块都能做到这一点。例如,创建一个小模块层次结构:
$ mkdir -p a/b
$ touch a/b/c.py
确保a下没有其他文件。启动Python 3.4或更高版本的解释器(例如,使用python3-i)并检查以下语句的结果:
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并启动一个新的解释器来演示这一点:
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没有。
任何Python文件都是一个模块,其名称是文件的基本名称,不带.py扩展名。包是Python模块的集合:虽然模块是单个Python文件,但包是包含额外__init__.py文件的Python模块目录,以区分包和恰好包含一堆Python脚本的目录。只要相应的目录包含自己的__init__.py文件,包可以嵌套到任何深度。
模块和包之间的区别似乎只在文件系统级别上存在。当您导入模块或包时,Python创建的相应对象总是模块类型。但是,请注意,当您导入包时,只有该包的__init__.py文件中的变量/函数/类是直接可见的,而不是子包或模块。例如,考虑Python标准库中的xml包:其xml目录包含__init__.py文件和四个子目录;子目录etree包含__init__.py文件,以及ElementTree.py文件。查看尝试以交互方式导入包/模块时发生的情况:
>>> 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编写的,但我不认为您打算在问题中考虑这些模块。
模块是在一次导入下导入并使用的单个文件。例如
import my_module
包是提供包层次结构的目录中的模块集合。
from my_package.timing.danger.internets import function_of_love
模块文档
软件包简介
从Python词汇表中:
重要的是要记住,所有包都是模块,但并非所有模块都是包。换句话说,包只是一种特殊的模块。具体来说,任何包含__path__属性的模块都被视为包。
名称中带有破折号的Python文件(如my-file.py)不能用简单的import语句导入。代码方面,importmyfile与importmy-file相同,这会引发异常。这样的文件更好地被描述为脚本,而可导入的文件是模块。
迟来的答案,还有另一个定义:
包由导入的顶级实体表示,该顶级实体可以是一个独立模块,或__init__.py特殊模块作为子目录结构中的一组模块中的顶级实体。
因此,包实际上是一个分发单元,它提供一个或多个模块。