python模块和python包有什么区别?

What's the difference between a Python module and a Python package?

python模块和python包有什么区别?

另请参见:"package"和"module"(其他语言)之间的区别是什么?


任何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语言编写的,但我认为您不打算考虑您所讨论的那些模块。


模块是在一次导入下导入并使用的单个文件(或多个文件)。例如

1
import my_module

包是目录中提供包层次结构的模块集合。

1
from my_package.timing.danger.internets import function_of_love

模块文档

软件包简介


从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-fileimport 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'>

模块aa.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/是一个目录,因此创建了一个名称空间包aa/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.

因此,从物理上讲,包是一个分发单元,它提供一个或多个模块。


所以你记得回到你的课本上,在内容页上,章节被划分成模块。因此,存在着不同的概念,不同的章节有相同的目标或部分相同的理论,然后这些部分聚集在一起,被称为模块。同样,在编程中,当不同的函数聚集在一起时,它们被分开并命名为模块。