Skip to content

Python 包导入

Python 包帮助我们管理模块和 Python 脚本。它们是普通的目录,其中包含一个初始化脚本——init.py。

如何创建Python包?

我们可以按照以下步骤创建软件包。

  1. 创建包目录——我们可以使用终端或Python IDE来完成此操作。
  2. 创建 init.py 文件——这是将普通目录转换为 Python 包所必需的。此文件用于初始化包并列出所有模块。最简单的情况下,此文件可以为空。

Python 包中可以包含哪些内容?

  • 初始化文件
  • Python 模块
  • Python脚本
  • 其他类型的文件

所以,一般来说,软件包就像我们计算机系统中的一个目录。唯一的区别在于,软件包必须包含__init__.py文件。

我们可以在Python中创建子包吗?

是的,我们可以在一个包内创建一个包。创建子包也需要遵循打包规则。

Python 包示例

让我们来看一些创建和使用软件包的例子。

1. 创建包

shell
$ mkdir utilities
$ touch utilities/__init__.py
$ mkdir utilities/strings
$ mkdir utilities/strings/__init__.py
$ tree
.
└── utilities
    ├── __init__.py
    └── strings
        └── __init__.py
 
3 directories, 1 file
$

Python 包结构

2. 向软件包添加模块

假设我们有两个 Python 模块——math.py和str_utils.py。它们包含一些将在我们的程序中使用的函数。

math.py:

python
def add(x, y):
    return x + y
 
def multiply(x, y):
    return x * y

str_utils.py:

python
def to_uppercase(s):
    s = str(s)
    return s.upper()
 
def reverse(s):
    s = str(s)
    return s[::-1]

我们希望将这些模块添加到我们的软件包中。只需将这些文件复制到您希望存放这些模块的软件包目录即可。

shell
$ ls
math.py      str_utils.py utilities
$ mv math.py utilities 
$ mv str_utils.py utilities/strings
$ tree
.
└── utilities
    ├── __init__.py
    ├── math.py
    └── strings
        ├── __init__.py
        └── str_utils.py
 
3 directories, 3 files
$

向 Python 包添加模块

3. 从包中导入模块

在包内导入 Python 模块的语法是:

python
import package.sub_package1.sub_package2.module
import package.sub_package1.sub_package2.module as module

Python 使用sys.path变量来查找包和模块。当前目录是该sys.path变量的一部分。因此,我们将把 Python 脚本放在python-packages目录中。否则,我们需要将包的位置添加到该sys.path变量中。

shell
$ cat my_script.py 
import sys
 
print(sys.path)
$ python3.7 my_script.py 
['/Users/pankaj/Desktop/python-packages', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python37.zip', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages']
$

以下是 my_script.py 中的代码,用于访问包中的模块并调用它们的函数。

python
import utilities.math as math
import utilities.strings.str_utils as str_utils
 
print(math.add(10, 20))
print(str_utils.reverse("ABC"))

在 Python 中导入包模块

我们还可以使用以下语法导入模块:

python
from package.sub_package1.sub_package2 import module

以下是更新后的示例,用于在我们的程序中访问“math”和“str_utils”模块。

python
from utilities import math
from utilities.strings import str_utils
 
print(math.add(10, 20))
print(str_utils.reverse("ABC"))

Python 从包导入模块

4. 从包中导入 *

我们可以使用以下语法从包中导入每个模块。

python
from package.sub_package1.sub_package2 import *

在这种情况下,Python 会在 sub_package2 中搜索包、模块和函数。这可能会导致导入一些你不想导入的内容,从而产生副作用。此外,这个过程非常耗时。

我们可以通过在 init.py 文件中创建__all__变量来定义要导入的模块列表。

utilities/init.py:

python
print('utilities package initialized')
 
__all__ = ['math']

utilities/strings/init.py:

python
print('utilities.strings package initialized')
 
__all__ = ['str_utils']

更新后的 my_script.py 代码如下:

python
from utilities import *
from utilities.strings import *
 
print(math.add(10, 20))
print(str_utils.reverse("ABC"))

输出:

shell
$ python3.7 my_script.py 
utilities package initialized
utilities.strings package initialized
30
CBA

Python 包初始化文件所有模块列表

请注意,在初始化和导入包时,init.py 中的 Python 代码会首先执行。

如何将软件包添加到系统路径

始终依赖目录层级结构来导入包模块是不可行的。我们可以将自定义包添加到 sys.path 变量中,然后在任何脚本中导入它们。

python
import sys
 
sys.path.append("/Users/pankaj/Desktop/python-packages")
 
print(sys.path)
 
import utilities.math as math
 
print(math.add(1, 2))

输出:

shell
$ python3.7 my_script.py 
['/Users/pankaj', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python37.zip', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages', '/Users/pankaj/Desktop/python-packages']
utilities package initialized
3
$

结论

Python 中的包机制允许我们将应用程序模块和脚本划分成逻辑模块。这使得我们的代码库保持整洁,易于维护。

参考: