如何打包 Python package 并发布到 PyPi

前段时间为了方便预定学校的羽毛球场,写了一个简单的脚本来自动提交请求。为了方便分发给别人使用,同时保证相对匿名,想了许多方法。最开始专门新建了一个 GitHub 账号,使用匿名 Gist 发布代码。后来发现国内连通性太差,同时更新也不是怎么方便,于是研究了一下如何打包发布到 PyPi,可以更简单地安装和使用。

注册 PyPi 账号

首先前往官网注册一个自己的账号,并生成一个 API Token,记录下来。之后前往 $HOME 目录,新建一个 .pypirc 配置文件,只需要将 password 改为上面 Token 即可。

1
2
3
[pypi]
username = __token__
password = <YOUR_TOKEN>

配置包文件

主文件

下面给出一个简单的例子,假定包名(文件夹名)为 example,其中主要文件为 example.py

1
2
3
4
5
6
7
8
9
10
11
# example.py
class Example()

def __init__(self, name):
print(f'hello {name}!')

def main():
example = Example('world')

if __name__ == '__main__':
main()

__init__.py

要想被 python 识别成包,根目录下必须包含 __init__.py 文件。如果之前没有的话,新建一个文件,并导入包即可。

1
from example import Example, main

__main__.py

如果想要自己的包可以用 python -m your_package 的方式执行,需要添加 __main.py__,即给自己的包增加一个 main 函数。

1
2
3
from example import main

main()

配置 setup.py

下面进入上一层目录,配置打包所需要的 setup.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from setuptools import setup

setup(
name='example',
version='0.0.1',
python_requires='>=3.6.0',
author='Editst',
author_email='editst@example.com',
url='https://editst.com',
description='Example Python Package',
long_description=r'**Example Python Package**',
long_description_content_type='text/markdown',
packages=['example'],
entry_points={
'console_scripts': ['example=example:main'],
},
install_requires=[],
classifiers=[
'License :: OSI Approved :: MIT License',

'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
],
)

需要注意的是其中的 entry_points,这个是用来在命令行中执行脚本的,这里我们只需要添加一个 example 即可。安装之后就可以直接在命令行运行 example,就是执行 example.main() 函数。

其中的 classifiers 可以设置包的类别,可以参考这里,比较常用的是指定开源协议和适用的 python 版本。

打包上传

首先需要安装打包和上传所需的工具。

1
python -m pip install twine wheel setuptools

之后打包上传即可。

1
2
python setup.py sdist bdist_wheel
python -m twine upload dist/*

之后就可以在 PyPi 上搜索到我们的包了。