打造你的 Python 包:告别单打独斗,分享代码到 PyPI 怎么发布?这问题,折腾过多少人啊!
话说回来,写代码这事儿,绝大部分时候都是自娱自乐,或者团队内部消化。但总有那么一刻,你觉得,“嘿,这个小工具写得不错,这块功能封装得挺好,说不定其他人也能用上呢?” 那种 itch,那种想把自己的宝贝分享出去的冲动,特真实。然后,问题就来了,python 怎么发布?不是简单地把 .py
文件发给朋友,而是要堂堂正正地放到PyPI(Python Package Index)上,让全世界的 Python 开发者都能通过 pip install你的包名
一键安装。听起来是不是有点小激动?但也伴随着一丝丝懵圈。
我第一次琢磨这事儿的时候,那感觉,就像站在一片迷雾森林前。文档看了一堆,什么 setup.py
啊,setup.cfg
啊,MANIFEST.in
啊,wheel
啊,sdist
啊,twine
啊……这些词汇像一个个小精灵在你眼前乱窜,抓住一个吧,发现它又牵扯出另一串。特别是那个 setup.py
文件,看别人的,感觉就像在读天书,各种参数,各种依赖声明,头大!“声明入口点?”“指定运行环境?”“依赖怎么写?”每一个都是问号。
但你想啊,那么多牛人写了那么多好用的库,requests、Django、pandas,哪个不是这么发布的?说明这事儿肯定有条路可走,而且一旦走通,那种成就感,值了!所以,别怕,咱们一步步来,用“人话”聊聊这流程,少点条条框框的教程味儿,多点摸索的真实感。
首先,你得有个项目。别笑,这第一步听着简单,其实也藏着学问。你的代码,得有个结构吧?通常,大家会建议你搞个这样的目录:
your_package_name/
├── your_package_name/ <-- 放你真正的代码的地方
│ ├── __init__.py <-- 这个不能少,让 Python 知道这是个包
│ └── your_module.py
├── tests/ <-- 测试文件(很重要!)
│ └── test_something.py
├── README.md <-- 项目说明,必须有!让人知道你这玩意儿是干啥的
├── LICENSE <-- 版权信息,选个合适的开源协议
├── requirements.txt <-- 你的项目运行时需要的第三方库列表(虽然不是必须在发布时用它,但习惯好)
└── setup.py 或 pyproject.toml <-- 核心配置文件,告诉打包工具怎么处理你的项目
看,这就是个基本的项目骨架。以前,setup.py
是绝对的主角,用 setuptools
这个库来定义一切。写一个 setup.py
就像写个小脚本:
“`python
from setuptools import setup, find_packages
setup(
name=’your_package_name’,
version=’0.1.0′, # 版本号,每次发布新版本要改
packages=find_packages(exclude=[‘tests*’]), # 自动找到你的包目录
install_requires=[ # 你的项目依赖哪些库
‘requests’,
‘beautifulsoup4>=4.9.0′,
# … 其他依赖
],
python_requires=’>=3.6′, # 要求 Python 版本
description=’A short description of your package’,
long_description=open(‘README.md’).read(),
long_description_content_type=’text/markdown’, # 说明你的 README 是 markdown 格式
url=’https://github.com/yourusername/your_package_name’, # 你的项目仓库地址
author=’Your Name’,
author_email=’your.email@example.com’,
classifiers=[ # 分类信息,方便别人搜索
‘Programming Language :: Python :: 3’,
‘License :: OSI Approved :: MIT License’,
‘Operating System :: OS Independent’,
# … 更多分类
],
)
“`
是不是有点眼花缭乱?这还只是个基础版。实际写的时候,还有各种参数,比如入口点(entry points),如果你想让你的包安装后能直接运行一个命令行工具。配置这些玩意儿,特别是处理各种依赖版本冲突,有时候真能让人抓狂。
好在,时代在进步!现在打包这件事,有了新的“网红”——pyproject.toml
。这个文件是 PEP 518 引入的,目标是统一 Python 项目的配置方式。配合像 Poetry 或者 Flit 这样的构建工具,你可以告别 setup.py
的脚本式写法,用更声明式的方式来管理项目依赖和构建配置。比如用 Poetry,你的 pyproject.toml
会是这样:
“`toml
[tool.poetry]
name = “your_package_name”
version = “0.1.0”
description = “A short description”
authors = [“Your Name your.email@example.com“]
readme = “README.md”
homepage = “https://github.com/yourusername/your_package_name”
[tool.poetry.dependencies]
python = “^3.6” # Python 版本要求
requests = “^2.25.1” # 依赖库和版本范围
beautifulsoup4 = “>=4.9.0,<5.0.0”
[tool.poetry.dev-dependencies] # 开发依赖,比如测试框架
pytest = “^6.2.2”
[build-system]
requires = [“poetry-core>=1.0.0”]
build-backend = “poetry.core.masonry.api”
“`
是不是感觉清晰多了?Poetry 还能帮你管理虚拟环境,解决依赖冲突,简直是强迫症的福音。当然,用 setuptools
配合 setup.cfg
也能达到类似效果,它也是一种声明式配置的方式,但 pyproject.toml
正在成为主流。
选好工具(setuptools/twine 组合,或者 Poetry),写好配置文件后,下一步就是构建(Build)了。构建的目的,是把你的源代码和相关信息,按照打包的标准,制作成可以分发的安装包。主要有两种格式:
- sdist (Source Distribution): 源代码分发包。它包含你的源代码、
setup.py
/pyproject.toml
、README、LICENSE 等文件。用户安装时,会用他们本地的 Python 环境和工具来构建和安装。 - wheel (Built Distribution): 预构建分发包。这是一种已经构建好的包,安装时只需要解压复制文件,无需再次构建,速度更快,也避免了用户环境差异带来的构建问题。推荐优先提供
wheel
包。
怎么构建呢?如果你用 setuptools
,通常会安装 wheel
库,然后在项目根目录运行命令:
bash
python setup.py sdist bdist_wheel
这会在你的项目根目录生成一个 dist/
目录,里面就有 .tar.gz
(sdist) 和 .whl
(wheel) 文件。
如果你用 Poetry,更简单:
bash
poetry build
Poetry 会自动生成 sdist
和 wheel
包,同样放在 dist/
目录下。你看,工具链顺畅了,事情就没那么烦心了。
构建好了包,放在 dist/
目录里,接下来就是发布到PyPI了。在真正往PyPI这个“正式环境”推之前,强烈建议你先推到TestPyPI上试试水。TestPyPI就像一个沙盒,你可以尽情测试你的发布流程和包是否能正常安装,又不污染PyPI。
去 TestPyPI (test.pypi.org) 和 PyPI (pypi.org) 各自注册一个账号。然后,你需要一个工具来上传你的包,最常用的是 twine。安装它:pip install twine
。
上传到 TestPyPI 的命令是:
bash
twine upload --repository testpypi dist/*
它会提示你输入 TestPyPI 的用户名和密码。上传成功后,你就可以在 TestPyPI 上找到你的包了,并且可以尝试用 pip install --index-url https://test.pypi.org/simple/ --no-deps your_package_name
来安装测试一下。--no-deps
是为了防止它意外从真实的 PyPI 下载依赖。
在 TestPyPI 上折腾满意了,确保一切都没问题(特别是版本号,发布到 PyPI 的版本号必须是全新的,不能是 PyPI 上已有的),就可以发布到真实的 PyPI 了。命令几乎一样,只是换个目标:
bash
twine upload dist/*
这次输入的是 PyPI 的用户名和密码。回车,稍等片刻,如果一切顺利,恭喜你!你的 Python 包就正式发布到了 PyPI 上!全世界的 Python 开发者,只要知道你的包名,都能通过 pip install your_package_name
来安装使用了。
那感觉,真的挺棒的。从零开始写代码,到整理成规范的项目,再到构建、测试、最终发布到一个全球化的平台,整个流程走下来,不光是分享了代码,更重要的是,你对整个 Python 生态的理解会更深一层。你知道了别人写的那些库是怎么来的,怎么维护的,怎么发布新版本的。
当然,发布出去只是第一步。后面还有维护,处理 issue,接受 pull request,发布新版本(记住,每次发布都要改版本号!)。这是一个持续的过程。
整个发布流程,看似几步命令,背后其实涉及项目管理、依赖声明、构建系统、发布工具链等一系列知识。PyPI、setuptools
、wheel
、twine
、poetry
这些关键字,都是这条路上的重要节点。
回头看,第一次摸索的时候,那些配置文件、那些命令,确实让人抓耳挠腮。但多试几次,多看看别人的开源项目是怎么做的,慢慢就摸出门道了。而且,像 Poetry 这样的新工具,确实大大简化了发布流程,降低了门槛。所以,如果你是新手,不妨从 Poetry 入手,它的体验会更流畅。如果你用 setuptools
习惯了,那也挺好,掌握核心原理更重要。
别犹豫了,把你那个藏在角落里的得意小代码,整理整理,按照这个思路,一步步来,把它发布出去吧!让更多人看到,让你的代码真正“活”起来。这个过程本身,就是一种成长。毕竟,python 怎么发布,不只是技术问题,更是关于分享、关于贡献、关于融入更广阔社区的故事。
评论(0)