问题:Python模块和Python包之间有什么区别?
Python模块和Python包之间有什么区别?
另请参阅:“程序包”和“模块”之间有什么区别(对于其他语言)
回答 0
模块是在一个导入下导入并使用的单个文件。例如
import my_module
软件包是目录中提供软件包层次结构的模块的集合。
from my_package.timing.danger.internets import function_of_love
回答 1
任何Python文件都是一个模块,其名称是文件的基础名称,不带.py
扩展名。甲包是Python模块的集合:而一个模块是一个Python文件,一个包是含有一个额外的Python模块的目录__init__.py
文件中,一个包从恰好包含一堆Python脚本的一个目录区分开。包可以嵌套到任何深度,只要相应的目录包含它们自己的__init__.py
文件即可。
模块和软件包之间的区别似乎仅在文件系统级别上存在。导入模块或包时,Python创建的相应对象始终为类型module
。但是请注意,当您导入软件包时,仅__init__.py
该软件包文件中的变量/函数/类是直接可见的,子软件包或模块则不可见。例如,考虑xml
Python标准库中的包:其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语言编写的,但我认为您并不是要考虑问题中的那些模块。
回答 2
重要的是要记住,所有软件包都是模块,但并非所有模块都是软件包。换句话说,包只是一种特殊的模块。具体来说,任何包含
__path__
属性的模块都被视为包。
名称中带有破折号的Python文件(如my-file.py
)无法通过简单的import
语句导入。代码明智的,import my-file
是一样的import my - file
,这将引发异常。这样的文件可以更好地描述为脚本,而可导入文件是模块。
回答 3
首先,请记住,按照其精确定义,模块是Python解释器内存中的对象,通常是通过从磁盘读取一个或多个文件来创建的。虽然我们可以非正式地称呼磁盘文件(例如a/b/c.py
“模块”),但实际上它并没有与其他来自其他来源(例如sys.path
)的信息组合在一起以创建模块对象,而是变成一个文件。
(例如,请注意,可以根据相同的sys.path
设置和其他设置,从同一个文件中加载名称不同的两个模块。这正是在解释器中python -m my.module
后面跟着的情况import my.module
;将有两个模块对象,__main__
并且my.module
都创建了来自磁盘上的同一文件,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
它不是软件包,因此不能拥有子模块。
您还可以在此处看到package模块a
具有__path__
属性(packages必须具有此属性),但非package模块a.b
则没有。
回答 4
一个较晚的答案,还有另一个定义:
包由导入的顶级实体表示,该顶级实体可以是一个独立的模块,也可以是
__init__.py
特殊模块,它是子目录结构中一组模块中的顶级实体。
因此,从物理上说,包装就是一个分配单元,它提供一个或多个模块。
回答 5
包也是一个模块,可以包含其他模块,“基于文件的简单模块和包(子包)”。与模块的包装类型相关的代码进入该__init__.py
文件。
import pack1
print(type(pack1))
而模块是一个简单的文件,可以包含函数,类,可运行代码等。导入模块后,它的行为就像一个对象,您可以通过该对象访问模块中定义的标识符。