本篇我们介绍 Python 中的包(package),学习如何使用包构建应用程序。

Python 包

假如我们需要开发一个大型应用,用于处理从下单到支付的销售流程。这个应用将会包含许多模块,随着模块数量的增加,很难在一个地方维护所有的模块。与此同时,我们也想要将模块按照一定的方式进行分组。此时,我们就需要使用包。

包可以按照层次结构组织模块。Python 包和模块的结构就像操作系统中的文件夹和文件。创建包就是创建一个文件夹,然后将相关的模块文件存储到该文件夹。

为了让 Python 将一个文件夹当作包使用,我们需要在文件夹中创建一个 __init__.py 文件。

注意,从 Python 3.3 开始引入了隐式命名空间包的功能,允许 Python 将一个没有 __init__.py 文件的文件夹当作包使用。

例如,下图显式了 sales 包的文件结构,包含了 order、delivery 以及 billing 三个包:

linux python将自定义文件夹作为module python怎么将文件夹变成包_包

导入包

使用 import 语句导入包的语法如下:

import package.module

然后,访问模块中对象的语法如下:

package.module.function

以下示例使用了 sales 包中 order、delivery 以及 billing 模块函数:

# main.py
import sales.order
import sales.delivery
import sales.billing


sales.order.create_sales_order()
sales.delivery.create_delivery()
sales.billing.create_billing()

为了简化代码,我们可以使用以下语句导入模块中的函数:

from module import function

例如:

# main.py
from sales.order import create_sales_order
from sales.delivery import create_delivery
from sales.billing import create_billing


create_sales_order()
create_delivery()
create_billing()

也可以在导入对象时进行重命名操作:

# main.py
from sales.order import create_sales_order as create_order
from sales.delivery import create_delivery as start_delivery
from sales.billing import create_billing as issue_billing


create_order()
start_delivery()
issue_billing()

包的初始化

按照惯例,当我们导入一个包时,Python 会执行包中的 __init__.py 文件。因此,我们可以在 __init__.py 文件文件中初始化包级别的数据。

以下示例在 sales 包的 __init__.py 文件中定义了一个默认的税率:

# __init__.py

# default sales tax rate
TAX_RATE = 0.07

在 main.py 文件中,我们可以访问 sales 包中的 TAX_RATE:

# main.py
from sales import TAX_RATE

print(TAX_RATE)

除了初始化数据之外,__init__.py 文件也可以用于导入其他包中的模块。例如:

# __init__.py

# import the order module automatically
from sales.order import create_sales_order

# default sales tax rate
TAX_RATE = 0.07

在 main.py 文件导入 sales 包之后,可以直接使用 create_sales_order 函数:

# main.py
import sales

sales.order.create_sales_order()

from package import *

当我们使用以下语句导入包中的全部对象:

from package import *

Python 会查找 __init__.py 文件。如果该文件存在,Python 将加载文件中一个特殊的列表 __all__ 中包含的所有模块。例如,我们可以在 __all__ 列表中添加以下模块:

# __init__.py

__all__ = [
    'order',
    'delivery'
]

然后在 main.py 文件中使用以下导入语句:

# main.py
from sales import *


order.create_sales_order()
delivery.create_delivery()

# cannot access the billing module

我们在 main.py 文件中访问了 order 和 delivery 模块中的函数。不过,我们无法使用 billing 模块,因为它不在 __all__ 列表中。

子包

Python 包可以包含子包。子包可以用于进一步组织模块。

下图中的 sales 包包含了三个子包:order、delivery 以及 billing。每个子包都有相应的模块。我们可以将其他与订单处理相关的模块放入 order 子包:

linux python将自定义文件夹作为module python怎么将文件夹变成包___all___02

包相关的操作也可以用于子包。例如,我们可以使用以下语句导入 order 子包中的函数:

# main.py
from sales.order import create_sales_order

create_sales_order()

总结

  • 一个 Python 包包含一个或多个模块。Python 使用文件夹和文件结构管理包和模块。
  • __init__.py 文件用于初始化包级别的数据。
  • __all__ 变量中的模块会在导入包时自动加载。
  • 包可以包含子包。