简体   繁体   English

Python模块和Python package有什么区别?

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

What's the difference between a Python module and a Python package? Python模块和Python package有什么区别?

See also: What's the difference between "package" and "module" (for other languages)另请参阅: “包”和“模块”之间有什么区别(对于其他语言)

Any Python file is a module , its name being the file's base name without the .py extension.任何 Python 文件都是一个module ,它的名称是文件的基本名称,没有.py扩展名。 A package is a collection of Python modules: while a module is a single Python file, a package is a directory of Python modules containing an additional __init__.py file, to distinguish a package from a directory that just happens to contain a bunch of Python scripts.是 Python 模块的集合:模块是单个 Python 文件,而包是 Python 模块的目录,其中包含一个额外的__init__.py文件,以将包与恰好包含一堆 Python 的目录区分开来脚本。 Packages can be nested to any depth, provided that the corresponding directories contain their own __init__.py file.包可以嵌套到任何深度,前提是相应的目录包含自己的__init__.py文件。

The distinction between module and package seems to hold just at the file system level.模块和包之间的区别似乎只存在于文件系统级别。 When you import a module or a package, the corresponding object created by Python is always of type module .导入模块或包时,Python 创建的相应对象始终为module类型。 Note, however, when you import a package, only variables/functions/classes in the __init__.py file of that package are directly visible, not sub-packages or modules.但是请注意,当您导入包时,只有该包的__init__.py文件中的变量/函数/类是直接可见的,而不是子包或模块。 As an example, consider the xml package in the Python standard library: its xml directory contains an __init__.py file and four sub-directories;以Python标准库中的xml包为例:它的xml目录包含一个__init__.py文件和四个子目录; the sub-directory etree contains an __init__.py file and, among others, an ElementTree.py file.子目录etree包含一个__init__.py文件,以及一个ElementTree.py文件。 See what happens when you try to interactively import package/modules:看看当您尝试以交互方式导入包/模块时会发生什么:

>>> 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>

In Python there also are built-in modules, such as sys , that are written in C, but I don't think you meant to consider those in your question.在 Python 中,还有一些内置模块,例如sys ,它们是用 C 编写的,但我不认为您打算在问题中考虑这些模块。

A module is a single file (or files) that are imported under one import and used.模块是在一次导入下导入并使用的单个文件(或多个文件)。 eg例如

import my_module

A package is a collection of modules in directories that give a package hierarchy.包是提供包层次结构的目录中的模块集合。

from my_package.timing.danger.internets import function_of_love

Documentation for modules模块文档

Introduction to packages 包介绍

First, keep in mind that, in its precise definition, a module is an object in the memory of a Python interpreter, often created by reading one or more files from disk.首先,请记住,在其精确定义中,模块是 Python 解释器内存中的一个对象,通常通过从磁盘读取一个或多个文件来创建。 While we may informally call a disk file such as a/b/c.py a "module," it doesn't actually become one until it's combined with information from several other sources (such as sys.path ) to create the module object.虽然我们可以非正式地将诸如a/b/c.py类的磁盘文件称为“模块”,但在它与来自其他几个来源(例如sys.path )的信息结合以创建模块对象之前,它实际上不会成为一个模块.

(Note, for example, that two modules with different names can be loaded from the same file, depending on sys.path and other settings. This is exactly what happens with python -m my.module followed by an import my.module in the interpreter; there will be two module objects, __main__ and my.module , both created from the same file on disk, my/module.py .) (注意,例如,不同名称的两个模块可以从同一个文件被加载,这取决于sys.path与发生和其他设置。这正是python -m my.module后跟import my.module在解释器;将有两个模块对象, __main__my.module ,它们都是从磁盘上的同一个文件my/module.py 。)

A package is a module that may have submodules (including subpackages).是可能有子模块(包括子包)的模块。 Not all modules can do this.并非所有模块都可以做到这一点。 As an example, create a small module hierarchy:例如,创建一个小的模块层次结构:

$ mkdir -p a/b
$ touch a/b/c.py

Ensure that there are no other files under a .确保没有在任何其他文件a Start a Python 3.4 or later interpreter (eg, with python3 -i ) and examine the results of the following statements:启动 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'>

Modules a and ab are packages (in fact, a certain kind of package called a "namespace package," though we wont' worry about that here).模块aab是包(实际上,某种称为“命名空间包”的包,尽管我们不会在这里担心)。 However, module abc is not a package.然而,模块abc不是一个包。 We can demonstrate this by adding another file, a/b.py to the directory structure above and starting a fresh interpreter:我们可以通过在上面的目录结构中添加另一个文件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 ensures that all parent modules are loaded before a child module is loaded. Python 确保在加载子模块之前加载所有父模块。 Above it finds that a/ is a directory, and so creates a namespace package a , and that a/b.py is a Python source file which it loads and uses to create a (non-package) module ab .在它上面发现a/是一个目录,因此创建了一个命名空间包a ,而a/b.py是一个 Python 源文件,它加载并用于创建(非包)模块ab At this point you cannot have a module abc because ab is not a package, and thus cannot have submodules.此时你不能有模块abc因为ab不是一个包,因此不能有子模块。

You can also see here that the package module a has a __path__ attribute (packages must have this) but the non-package module ab does not.您还可以在此处看到包模块a具有__path__属性(包必须具有此属性)但非包模块ab没有。

From the Python glossary :来自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.具体来说,任何包含__path__属性的模块都被视为一个包。

Python files with a dash in the name, like my-file.py , cannot be imported with a simple import statement.名称中带有破折号的 Python 文件(例如my-file.py )无法使用简单的import语句import Code-wise, import my-file is the same as import my - file which will raise an exception.代码明智的, import my-file是相同的import my - file ,这将引发异常。 Such files are better characterized as scripts whereas importable files are modules .这样的文件被更好地描述为脚本,而可导入的文件是模块

A late answer, yet another definition:一个迟到的答案,另一个定义:

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.包由导入的顶级实体表示,该实体可以是自包含模块,也可以是__init__.py特殊模块作为子目录结构中一组模块的顶级实体。

So physically a package is a distribution unit, which provides one or more modules.所以物理上一个包是一个分发单元,它提供一个或多个模块。

Module : A module is a simple Python file with a ( .py ) extension that contains collections of functions and global variables.模块:模块是一个简单的 Python 文件,扩展名为 ( .py ),其中包含 collections 的函数和全局变量。 It is an executable file, and the notion of Package in Python is used to arrange all of the modules.它是一个可执行文件,Python中Package的概念用于排列所有的模块。

For an Example : Save the code in a file called demo ( module.py ).例如:将代码保存在名为 demo ( module.py ) 的文件中。

def myModule1(name):
    print("My Module name is: "+ name)

Import the demo module module and use the myModule1 function within it.导入演示模块模块并使用其中的 myModule1 function。

import demo_module
  
demo_module.myModule1("Math")

Solution:解决方案:

My Module name is: Math我的模块名称是:Math

Package: A package is a basic directory that contains a collection of modules. Package: package 是包含模块集合的基本目录。 This directory contains Python modules as well as a ( __init.py__ ) file that the interpreter uses to recognize it as a Package. The package is nothing more than a namespace.该目录包含 Python 模块以及解释器用来将其识别为 Package 的 ( __init.py__ ) 文件。package 只不过是一个命名空间。 Within the package, there are sub-packages. package里面有子包。

For an Example:例如:

Student (Package)学生(套餐)

| | __init__.py (Constructor) __init__.py .py(构造函数)

| | details.py (Module) details.py (模块)

| | marks.py (Module) marks.py (模块)

| | collegeDetails.py (Module) collegeDetails.py (模块)

| | demo_module.py (Module) demo_module.py (模块)

A package is a set of modules organized into directories to form a package directory.一个package是一组模块组织成目录,形成一个package目录。

from Student import details, collegeDetails, demo_module

I read the different answers given to this question.我阅读了对这个问题的不同答案。 The issue is fully covered.该问题已完全涵盖。 But it seems to me that making an extra point may not be a bad idea.但在我看来,提出额外的观点可能不是一个坏主意。 If we examine the value of __package__ for different modules, we reach the following result.如果我们检查不同模块的__package__值,我们会得到以下结果。 All of them are module types but for some of them the package is not defined.它们都是模块类型,但对于其中一些没有定义包。 Check __package__ for " random " and " math ".检查__package__的“随机”和“数学”。

import cv2
import math
import random
import tkinter as tk

print('cv2:',type(cv2))             # <class 'module'>
print('cv2:',cv2)                   # <module 'cv2.cv2' from 'PATH'>
print('cv2:',cv2.__package__)       # cv2

print('random:',type(random))       # <class 'module'>
print('random:',random)             # <module 'random' from 'PATH'>
print('random:',random.__package__) # [EMPTY]

print('tk:',type(tk))               # <class 'module'>
print('tk:',tk)                     # <module 'tkinter' from 'PATH'>
print('tk:',tk.__package__)         # tkinter

print('math:',type(math))           # <class 'module'>
print('math:',math)                 # <module 'math' (built-in)>
print('math:',math.__package__)     # [EMPTY]

So if we define a folder as follows:所以如果我们定义一个文件夹如下:

在此处输入图片说明

This is how we can see the __package__ output:这是我们如何看到__package__输出:

import myfolder
import myfolder.script1 as s1
import myfolder.script2 as s2
import myfolder.mySubfolder.script3 as s3

print(type(s1)) # <class 'module'>
print(type(s2)) # <class 'module'>
print(type(s3)) # <class 'module'>

print(s1.__package__) # myfolder
print(s2.__package__) # myfolder
print(s3.__package__) # myfolder.mySubfolder

print(myfolder)                     # <module 'myfolder' (namespace)>
print(myfolder.mySubfolder)         # <module 'myfolder.mySubfolder' (namespace)>
print(myfolder.mySubfolder.script3) # <module 'myfolder.mySubfolder.script3' from 'PATH'>

print(myfolder.__package__)                     # myfolder        
print(myfolder.mySubfolder.__package__)         # myfolder.mySubfolder
print(myfolder.mySubfolder.script3.__package__) # myfolder.mySubfolder

The other answers here may still be a bit vague, so I'm posting a hopefully clearer answer.这里的其他答案可能仍然有点模糊,所以我发布了一个希望更清晰的答案。 It's important to note that the title of the question is also a bit misleading in the first place, and a better title in my opinion would be: " What is special about package modules compared to regular modules? " .重要的是要注意,问题的标题首先也有点误导,我认为更好的标题是: 与常规模块相比,包模块有什么特别之处?

TL;DR - Short Answer: TL;DR - 简答:

Packages are modules too, they are however, a special type of them.包也是模块,然而,它们是模块的一种特殊类型。 Special in the sense that 1. they are "directories" and 2. they may contain special files such as __init__.py and __main__.py .特殊意义在于1.它们是“目录”, 2.它们可能包含特殊文件,例如__init__.py__main__.py

To Better Understand - Longer Answer:为了更好地理解 - 更长的答案:

The point is, packages are a special type of modules , so we need to understand modules in general first, and then what's special about the package modules will make sense too.关键是,包是一种特殊类型的模块,所以我们需要先了解模块的一般性,然后包模块的特殊之处也就有意义了。 (Notice: I'll sometimes refer to "package modules" in this answer as just "packages", and vice versa) (注意:我有时会在这个答案中将“包模块”称为“包”,反之亦然)

So let's talk about modules in general first, as it would be less vague / easier to understand.所以让我们先谈谈一般的模块,因为它会不那么模糊/更容易理解。 There are basically two things that we do with modules, we either import them in other modules, or execute them directly by Python.基本上我们对模块做了两件事,我们要么将它们导入到其他模块中,要么直接通过 Python 执行它们。

Importing a module has a single obvious goal, accessing what that module has inside.导入模块有一个明显的目标,即访问该模块内部的内容。

Executing a module however, usually pursues one of these two goals:然而,执行一个模块通常会追求以下两个目标之一:

  1. That module is a main module and executing it will start our program (or one of its subprograms).该模块是一个主模块,执行它将启动我们的程序(或其子程序之一)。
  2. We want to try the functionalities of that module in isolation, ie, without having to import it first.我们想单独尝试该模块的功能,即不必先导入它。

Let's make more sense of all these through some examples:让我们通过一些例子来了解所有这些:

Importing modules:导入模块:

# bar.py

def talk():
    print("bar")
# foo.py

import bar # <-- importing module "bar"

bar.talk() # <-- prints "bar"

Executing Modules执行模块

Goal 1, executing a module as a main module:目标 1,执行一个模块作为主模块:

Let's assume that the foo.py module in the example above, is a main module that starts our program.让我们假设上面例子中的foo.py模块是启动我们程序的主模块。 We can run it by typing this command in the terminal: python3 foo.py # <-- executing a main module and then it will start our program.我们可以通过在终端中输入以下命令来运行它: python3 foo.py # <-- executing a main module ,然后它将启动我们的程序。

Goal 2, trying functionalities of a module in isolation:目标 2,单独尝试模块的功能:

Let's assume that we want to try the function talk in the bar.py module in the example above, without running our whole program, ie, without calling the module foo.py .让我们假设我们想在上面的例子中尝试bar.py模块中的函数talk ,而不运行我们的整个程序,即不调用模块foo.py For that, we'll have to slightly change the bar.py :为此,我们必须稍微更改bar.py

# bar.py

def talk():
    print("bar")

if __name__ == '__main__':
    talk()

Now run this command in the terminal: python3 bar.py # <-- trying functionalities of a module in isolation and then it will print bar .现在在终端中运行此命令: python3 bar.py # <-- trying functionalities of a module in isolation然后它将打印bar

Now that we know what we can do with modules in general, let's return to the main question:现在我们知道了我们可以用模块做什么,让我们回到主要问题:

What is special about package modules compared to regular modules?与常规模块相比,包模块有什么特别之处?

1. Regular modules in Python are just "files", package modules are however, "directories". 1. Python 中的常规模块只是“文件”,而包模块是“目录”。

2. Regular modules can be "imported" and can be "executed" (as shown in the examples above), package modules ALSO can be "imported" and can be "executed", HOWEVER, you may rightly complain: " but we can't directly write code in directories! Code is written in files only!" 2. 常规模块可以“导入”和“执行”(如上例所示),包模块也可以“导入”和“执行”,但是,您可能会抱怨:“但我们可以'不要直接在目录中写代码!代码只写在文件中!” , and that's indeed a very good complaint, as it leads us to the second special thing about package modules. ,这确实是一个很好的抱怨,因为它使我们想到了关于包模块的第二个特殊之处。 The code for a package module is written in files inside its directory , and the names of these files are also reserved by Python.包模块的代码写在其目录下的文件中,这些文件的名称也由 Python 保留。 If you want to "import" a package module, you'll have to put its code in an __init__.py file in its directory, and if you want to "execute" a package module, you'll have to put the execution code of it in a __main__.py file in its directory.如果你想“导入”一个包模块,你必须把它的代码放在它的目录下的__init__.py文件中,如果你想“执行”一个包模块,你必须把执行代码它在其目录中的__main__.py文件中。

And here's the final example for the explanation above:这是上述解释的最后一个例子:

# hierarchy of files and folders:
.
├── bar_pack/
│   ├── __init__.py
│   ├── __main__.py
│   foo.py
# bar_pack/__init__.py

def talk():
    print("bar")
# bar_pack/__main__.py

import __init__

__init__.talk()
# foo.py

import bar_pack # <-- importing package module "bar_pack"

bar_pack.talk() # <-- prints "bar"
# Run this command in the terminal:
python3 bar_pack # <-- executing the package module "bar_pack", prints "bar"

I know, it's too late, but a simple answer which would be sufficient for some is:我知道,为时已晚,但对某些人来说足够的简单答案是:

a module is a file,一个模块是一个文件,

a package is a folder.一个包是一个文件夹。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM