有人喜欢在requirements.txt里写“>=”号,比如Django>=3.2。这看起来很灵活,但用户机器上可能装了个新版本,你不一定测试过。差一个版本,接口改了,你的代码就崩。建议固定主版本号。比如Django>=3.2,<4.0。或者用“==”直接卡死小版本。自己辛苦点维护,用户就不用替你背锅。 第二点,别以为pip install就完事了,setup.py里记得写entry_points。很多人把脚本塞进包就发出去,用户装完发现命令行找不到命令。正确做法是在setup.py里用console_scripts。比如entry_points={'console_scripts': ['myapp=myapp.main:main']},这样用户装完直接在终端敲myapp就能跑。省得用户自己去翻bin目录。
第三点,处理数据文件要显眼,别藏起来。Python包安装后,数据文件可能跑到site-packages的角落里。你的代码里如果用了'/data/config.json'这类绝对路径,用户安装后一运行就报文件不存在。解决方法是用pkg_resources或者importlib.resources来读取包内的文件。或者把配置文件放到用户家目录里,第一次运行自动生成。不管哪种方法,都要在文档里写清楚文件在哪。
第四点,考虑操作系统差异。Windows上路径是反斜杠,Linux是斜杠。你的代码里如果用os.path.join或者pathlib能自动处理好。但要注意换行符,Windows是\r\n,Linux是\n。如果你写了个脚本,处理文本文件时忘了这个,用户那边可能多出一堆^M。测试时至少在Windows和Linux各跑一遍。
第五点,二进制扩展包要提供预编译版本。如果你的项目依赖了numpy, pandas这种C扩展包,用户自己编译可能失败。Windows用户更常见,没装Visual Studio编译工具,直接报错。你可以用cibuildwheel来生成多个平台的wheel包。或者上传到PyPI前,用pip download把它们预打包好。用户只需装你给的wheel,不用再扛编译的痛。
第六点,给你的包写一个简单的安装说明。别只放一个requirements.txt就当文档。你至少要告诉用户:Python版本下限,比如3.8+。有没有系统级依赖,比如需要安装libxml2-dev。怎么验证安装成功,比如跑一个hello world例子。把这些写进README第一段,用户能少发几十封邮件问你。
打包其实不复杂,就是细节多。你把上面六点检查一遍,用户安装时大概率能一气呵成。我自己每次发版前会找一台干净的虚拟机,从零装一遍。装通了再发布。用户顺畅,你也省心。