# Python 中的软件包

> 原文： [http://zetcode.com/lang/python/packages/](http://zetcode.com/lang/python/packages/)

在 Python 编程教程的这一部分中，我们介绍了程序包。

Python 包是具有通用目的的模块的集合。 软件包目录必须有一个名为`__init__.py`的特殊文件。 （从 Python 3.3 开始，不再需要`__init__.py`来定义软件包目录。）Python 模块是单个 Python 文件。

当我们处理包含成百上千个模块的大型项目时，使用包至关重要。 例如，我们可以将所有与数据库相关的模块放在一个数据库包中，并将用户界面代码放在`ui`包中。

内置软件包可在预定义目录中使用； 例如 Debian Linux 上的`/usr/lib/python3.5`或`C:\Users\Jano\AppData\Local\Programs\Python\Python36-32\Lib\site-packages`。

第三方软件包已安装到预定义目录中，例如 Debian Linux 上的`/usr/local/lib/python3.5/dist-packages`或 Windows 上的`C:\Users\Jano\AppData\Local\Programs\Python\Python36-32\libs`。

## Python 包管理

Python 软件包由 Python 软件包管理器`pip`进行管理。

```py
$ sudo pip3 install arrow

```

例如，使用上述命令安装了箭头库。

```py
$ sudo pip3 uninstall arrow

```

要卸载箭头，我们使用上面的命令。

## 空`__init__.py`的 Python 软件包

在第一个示例中，我们使用 Python 创建一个简单的程序包。

```py
$ tree
.
├── mymath
│   ├── __init__.py
│   └── mfuns.py
└── myprog.py

```

在当前工作目录中，我们有一个`mymath`目录和一个`myprog.py`脚本。 `mymath`包含`__init__.py`文件，该文件将`mymath`目录标记为软件包目录。

`mymath`目录有两个文件：`__init__.py`文件使常量成为 Python 软件包目录，而`mfuns.py`是 Python 模块。

`__init__.py`

`__init__.py`为空白。 它可以包含一些代码，但也可以为空。

`mfuns.py`

```py
def mycube(x):

   return x * x * x 

```

在`mfuns.py`模块中，我们定义了`cube()`函数。

`myprog.py`

```py
#!/usr/bin/env python

# myprog.py

from mymath.mfuns import mycube

print(mycube(3))

```

在`myprog.py`程序中，我们从`mymath.mfuns`模块导入`mycube`功能。 模块名称和程序包名称用点字符分隔。

## `__init__.py`中的 Python 导入功能

在下一个示例中，我们在`__init__.py`文件中有一些代码。

```py
$ tree
.
├── mymath
│   ├── __init__.py
│   └── mfuns.py
└── myprog.py

```

我们具有相同的目录结构。

`__init__.py`

```py
from .mfuns import mycube

```

在`__init__.py`文件中，我们导入`mycube`功能。 结果，当我们从`mymath`包中引用`mycube`函数时，我们不必指定模块名称。

`mfuns.py`

```py
def mycube(x):

   return x * x * x 

```

在`mfuns.py`模块中，我们定义了`cube()`函数。

`myprog.py`

```py
#!/usr/bin/env python

# myprog.py

from mymath import mycube

print(mycube(3))

```

在`myprog.py`程序中，我们导入`mycube`功能。 这次我们省略了模块名称。

## 没有`__init__.py`的 Python 包

从 Python 3.3 开始，无需使用`__init__.py`文件就可以定义软件包目录。

```py
read.py
constants/
    data.py 

```

在当前工作目录中，我们有一个`constants`目录和一个`read.py`脚本。

`data.py`

```py
colours = ('yellow', 'blue', 'red', 'orange', 'brown')
names = ('Jack', 'Jessica', 'Robert', 'Lucy', 'Tom')

```

`data.py`模块有两个元组。

`read.py`

```py
#!/usr/bin/env python

# read.py

from constants.data import colours
import constants.data as mydata

print(colours)
print(mydata.names)

```

在`read.py`脚本中，我们导入元组并将其打印到终端。

```py
$ ./read.py 
('yellow', 'blue', 'red', 'orange', 'brown')
('Jack', 'Jessica', 'Robert', 'Lucy', 'Tom')

```

## Python `arrow`包

`arrow`是用于在 Python 中处理日期和时间的第三方库。

```py
$ ls /usr/local/lib/python3.5/dist-packages/arrow
api.py  arrow.py  factory.py  formatter.py  __init__.py  
locales.py  parser.py  __pycache__  util.py

```

该库安装在 Debian Linux 中`dist-packages`下的`arrow`目录中。 该库随`pip`软件包管理器一起安装。 如我们所见，该库是 Python 模块的集合。

## Python 子包

我们还可以创建子包。 要访问子包，我们使用点运算符。

```py
$ tree
.
├── constants
│ ├── __init__.py
│ ├── data.py
│ └── numbers
│     ├── __init__.py
│     └── myintegers.py
└── read.py

```

这是新的层次结构。 我们有一个称为数字的子包。

`constants/__init__.py`

```py
from .data import names

```

这是`constants`目录中的`__init__.py`文件。 我们导入`names`元组。

`constants/data.py`

```py
names = ('Jack', 'Jessica', 'Robert', 'Lucy', 'Tom')

```

这是`constants`目录中的`data.py`模块。 它包含`names`元组。

`numbers/__init__.py`

```py
from .myintegers import myintegers

```

数字包中的`__init__.py`文件具有这一行。

`numbers/myintegers.py`

```py
myintegers = (2, 3, 45, 6, 7, 8, 9)

```

整数模块定义了七个整数的元组。 该元组将通过`read.py`脚本进行访问。

`read.py`

```py
#!/usr/bin/env python

# read.py

from constants import names
from constants.numbers import myintegers

print(names)
print(myintegers)

```

这是`read.py`程序。 我们从`constants`包中导入`names`元组，并从`constants.numbers`子包中导入`myintegers`元组。

```py
$ ./read.py 
('Jack', 'Jessica', 'Robert', 'Lucy', 'Tom')
(2, 3, 45, 6, 7, 8, 9)

```

这是输出。

在本章中，我们介绍了 Python 包。