乐趣区

极简-Python3-打包指南

本文由 walker 整理自《pytest 测试实战·附录 D 打包和发布 Python 项目》·Brian Okken 著·华中科技大学出版社

walker 的实验环境

Windows 10 x64
Python  3.6.7 x64

项目的打包和发布很重要。大部分 Python 开发者对这一块并不熟悉,实际上,我们需要严肃地看待这个问题。毕竟,共享代码也是 Python 开发工作的一部分。因此,合理地使用 Python 内置的工具开共享代码很重要。虽然这是一个很大的话题,但由于篇幅的限制我无法全面介绍。这里只介绍常规的共享代码的方法。掌握这些方法后,至少你不必再用电子邮件发送压缩的文件和模块了。
我将介绍如何设置项目让它可以通过 pip 安装;如何以源代码形式发布项目;如何将项目打包成 wheel 文件。这些技巧足以让你在小型团队内部共享代码。如果你还希望通过 PyPI 将代码共享到互联网上,请阅读我推荐的文档。现在让我们开始吧。

创建可安装的模块

Creating an Installable Module

先学习如何让一个小项目可以被 pip 安装。我们以一个只有单一模块的项目为例。实际项目通常不会这么简单,我选择这个示例只是为了展示如何创建一个可维护的项目,以及 setup.py 文件可以多么简单。下面是一个简单的目录结构:

some_module_proj
  |--setup.py
  |--some_module.py

我们想要共享的代码在 some_molule.py 文件里:

# D:\Python3Project\test\some_module_proj\some_module.py
def some_func():
    return 42

要使其能被 pip 安装,我们需要一个 setup.py 文件。下面是最简介的 setup.py 代码:

# D:\Python3Project\test\some_module_proj\setup.py
from setuptools import setup
setup(
    name='some_module',
    py_modules=['some_module']
)

一个目录、一个模块、一个 setup.py 文件,就足以使项目能够被 pip 安装了。

D:\Python3Project\test
λ pip3 install .\some_module_proj\
Processing d:\python3project\test\some_module_proj
Installing collected packages: some-module
    Running setup.py install for some-module ... done
Successfully installed some-module-0.0.0

现在可以在 Python 程序里(或者从测试用例里)使用 some_molule 了。

D:\Python3Project>python
Python 3.6.7 (v3.6.7:6ec5cf24b7, Oct 20 2018, 13:35:33) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from some_module import some_func
>>> some_func()
42
>>> exit()

这是一种理想化的情况。在实际工作中,更常见的情况是将项目进行打包。下一节将介绍如何修改 setup.py 文件来完成项目打包。

创见可安装的包

Creating an Installable Package

先创建一个以包名名命的目录,然后将 __init__.py 文件和相关模块一同放入该目录里。

some_module_proj
 |--setup.py
 |--src
     |--some_package
         |--__init__.py
         |--some_module.py

some_module.py 文件的内容不变。__init__.py 文件需要把模块的功能通过包命名空间暴露给外部。由很多方式可以做到这一点,请阅读 Python 文档中关于该主题的两节内容(https://docs.python.org/3/tutorial/modules.html#packages)。
如果在 __init__.py 文件里这样写:

import some_package.some_module

那么调用端的代码必须指明 some_module。

退出移动版