尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Python 打包和分发方面学到的惨痛教训

Python 打包和分发方面学到的惨痛教训 打包和分发方面学到的惨痛教训引言为什么你的 代码只能在自己电脑上运行为数众多的开发者, 尤其是刚开始接触的新手, 都遭遇过这般的“甜蜜困扰”: 你精心撰写了一个出色的脚本或者小型应用程序, 它在你自己的电脑上运行得毫无瑕疵。然而当你满怀自信且满心期待地打算跟其他人分享的时候, 麻烦便接踵而至了。接收到的用户反馈并非是你代码存在的逻辑差错, 而是各种各样稀奇古怪的“安装失败”情况。你不禁开始对自身产生怀疑: 明明是一件看起来特别简单的事儿, 为何实际操作起来会如此艰难之极呢?曾经, 我也陷入这般困境, 我决定把自己费尽心力所写的代码进行打包并分享出去, 然而, 却撞上了一堵无形之墙, 也就是包的打包与分发这一状况。这看似简易的任务, 令我耗费一周时间, 在setup.py的报错里挣扎, 在依赖地狱中徘徊, 还遭遇来自用户“安装不了”的抱怨。在这篇文章里头, 我会毫无保留地去分享, 我从无数回失败当中总结得出的宝贵的经验。这些全部是我在将项目, 从“个人玩具”转变为“可供他人使用的工具”的进程里头, 一步一步踩坑收获而来的教训。期望我这些“硬核”经验, 能够助力你避开那些常见的陷阱, 使得你的代码真正迈向世界。第一课告别“万金油”式setup.py拥抱现代打包规范我最开始的打包尝试, 是手动去编写那个 setup.py 文件, 如同好多人那样, 我从 Stack 那儿东找西凑了一些代码片段, 而后把它们拼凑成一个看起来好像可行的文件, 那结果如何呢? 它在我的计算机上运行得顺顺当当的, 然而在其他任何其余的地方却都出现崩溃的情况了。我当时的setup.py看起来是这样的from setuptools import setup setup( namemypackage, version0.1, packages[mypackage], install_requires[numpy, pandas] )刚开始看的时候, 这个文件好像没什么毛病, 然而它有着诸多极为关键的细节缺失之处, 具体包括详细的描述 , 分类器 , 版本要求 , 还有可执行文件的入口点等等 , 这些缺失掉的信息 , 宛如一本没有目录以及封面的书 , 结果使得使用者没办法下手啦。我的教训在于, 单纯能够进行工作是不行的, 你需要给出充足的元数据, 以此使得用户清楚他们所安装的究竟是什么, 并且搞清使其运行所需要的条件是什么。一个更为完整、更契合现代规范的setup.py应当涵盖所有必要信息, 比如:from setuptools import setup, find_packages setup( namemypackage, version0.1.0, description一个有用的示例包, long_descriptionopen(README.md).read(), long_description_content_typetext/markdown, author你的名字, author_email你的邮箱example.com, urlhttps://github.com/你的用户名/mypackage, packagesfind_packages(), python_requires3.8, install_requires[ numpy1.21.0, pandas1.3.0 ], entry_points{ console_scripts: [ mypackagemypackage.cli:main ] }, classifiers[ Programming Language :: Python :: 3, License :: OSI Approved :: MIT License, Operating System :: OS Independent, ], )这个版本更为完善, 不止涵盖项目名称与版本, 还给出详细描述, 提供作者信息, 设有项目主页, 明确了依赖关系, 写明版本要求, 甚至有用于可执行文件的入口点、软件分类信息。如同给你的包附加上齐备的说明书添加了身份信息, 使它于茫茫的包海之中崭露头角, 也令用户能更安心地安装加以使用。核心要点第二课如何走出“依赖地狱”巧妙管理依赖关系我在早期的时候, 犯下了一个极为致命的错误, 其中之一便是: 对依赖版本太过严格。我曾把numpy的版本锁定成numpy1.21.0, 然而却没察觉到这会给那些需要numpy1.22的系统用户带去灾难性的后果。这情形就如同你要求所有人都得使用同一老旧型号的手机才能够安装你的应用, 这明显是不切实际的。较明智的举措是运用版本范围, 与此同时避开没必要的依赖, 比如说, 能够如此去指定依赖:install_requires [ numpy1.21,2.0, pandas1.3,2.0 ]它告知安装器, 只要numpy版本处于1.21至2.0这个范围之内2.0不涵盖, 均能够予以接受。这不但确保了兼容性, 还赋予了用户充足的灵活性。另外, 要是你的项目存在可选功能, 像某些得借助额外库方可运用的机器学习或者开发功能, 你应当予以采用。这能够令你把依赖项进行分组, 用户只需安装自身所需的部分, 而非将全部依赖一股脑儿地都安装好。例如extras_require { dev: [pytest, black], ml: [scikit-learn, tensorflow] }这么做之后, 用户能够依照自身需求来挑选安装, 像pip , 如此便仅仅会安装和机器学习有关联的依赖。这般一种方式使得你的包变得更为灵活 , 还减轻了用户的安装负担。核心要点第三课拥抱新标准从setup.py到.toml跟setup.py多次较量之后, 我察觉到, 社区正朝着一种全新的、更为现代的打包方式转变, 即PEP 517/518, 它的关键在于.toml文件。采取.toml最大的益处是, 它致使你的项目搭建变得跟工具没有关联, 你能选用任何支持这个标准的搭建工具去打包你的项目, 可不再遭受局限于此, 这使得整个打包流程变得越发清晰以及标准化。一个最小化的.toml示例是这样的[build-system] requires [setuptools61.0, wheel] build-backend setuptools.build_meta [project] name mypackage version 0.1.0 description 一个现代Python包 readme README.md requires-python 3.8 dependencies [ numpy1.21,2.0, pandas1.3,2.0 ]此文件简洁且明晰, 其对构建系统所需依赖予以定义, 还涵盖项目的基本元数据及其依赖关系, 采用这般方式后, 我工作流变得更干净、高效, 且与现代打包标准达成一致。核心要点第四课上线前必做本地测试是王道当我头一回把包推送至PyPI之际, 犯下了一个菜鸟层次的错误, 即上传了一个存在问题的构建包, 我未曾自本地开展任何测试之举, 便径直将其给予发行了, 这般行径恰似没经过试穿就甩手把衣服售卖给他人一样, 肯定会出现问题。PyPI 不让删除已发布的版本, 进而我的这个错误是永久的, 并且留下了不完美的记录。从那之后, 我形成了一种条理严谨的工作习性: 于把包上传至 PyPI 以前, 必定要在本地开展全面测试。我当下的准确流程是如此这般的:清理掉往昔的构建, 将先前构建的文件澈底除去, 保证一切事物皆为最新生成的。再度进行构建, 运用 -m build这个指令造就出全新的包文件。于本地加以装置测试, 借助pip dist / -0.1.0 - py3 - none - any. whl该项命令在本地安装所产生的这个包, 并查验其能不能正常运作。当我确认这个包在本地能够正确地进行安装, 并且可以正常运行的时候, 我才会去考虑把它推送到PyPI。核心要点第五课PyPI 是生产环境 是你的“沙盒”我的另外一个大错是, 直接于PyPI上开展实验, 我的头一回上传充斥着拼写差错、文件缺失以及版本冲突, 因为PyPI不准许删除已公开发布的版本, 这些“过往劣迹”便永久留存于我的项目页面上。自从那之后, 我掌握了于其上开展全部各种实验以及测试的技能。它是一种单独专门用来进行测试的包索引服务, 其运用的方式跟 PyPI 全然一模一样, 然而所有上传的那些包仅仅是被用于测试, 绝对不会对于正式的环境有所污染。上传到 的命令如下# 上传到 TestPyPI python -m twine upload --repository testpypi dist/*用户或者你自己可以从 安装你的包像这样pip install --index-url https://test.pypi.org/simple/ mypackage吾之教训乃, 把PyPI当作汝之生产环境, 而那什么东东则是汝之前发布之地或“沙盒”。于正式发布前, 先在那什么东东上搞完整之测试, 保证一切顺遂。如此可令汝免于在正式环境中留下任何没必要的错误记载。核心要点第六课用“语义化版本”建立用户信任我迅速发觉, 要是我的一次非主要更新, 也就是次要更新, 一不小心将用户的代码给弄坏了, 他们可是会万分恼怒的。这使得我察觉到, 版本号可不单单只是一个数字, 它更是一种许下的诺言。那个问题, 遵循语义化版本控制, 简是称, 给美妙地解决掉了呢。版本控制把版本号分作三部分呀 , 分别是MAJOR.MINOR.PATCH。始终如一地依照这个规则, 我和用户间构建起了信任, 他们清楚, 倘若我发布一个次要版本更新, 他们的代码不会因之而崩溃。核心要点第七课告别重复劳动自动化你的发布流程要手动把包上传至 PyPI, 这可是件既繁杂又极易出错之时。我找见自身一回又一回地径直重复同一命令: 去清理旧有文件, 再构筑新的包, 继而实施上传。是为了将这个问题予以弄清楚给解决掉, 所以呢最末尾之际我最终选定采用去开展我的一种方式用来做到自动化我所拥有的发布流程状态。当下目前, 每一次只要是我于上之际创建出来一个全新的之时, 这样的一种自动化工作流便会随之被触发启动, 它能够凭借自身自动去完成构建我的包, 并且还会把它推送至PyPI。一个基本的 工作流文件看起来像这样name: Publish Python Package on: release: types: [published] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkoutv2 - name: Set up Python uses: actions/setup-pythonv2 with: python-version: 3.9 - name: Install dependencies run: pip install build twine - name: Build and publish run: | python -m build python -m twine upload dist/* env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}这个自动化脚本, 极大程度地削减了我的工作量, 并且还杜绝了因依靠手动展开操作进而产生的错误。核心要点第八课从个人项目到社区贡献者打包是必经之路根据我的过往经历, 写出优秀的代码仅仅属于成功的其中一部分。而另外一部分, 同样具备关键意义的那一部分是保证这段代码针对其他人而言是能够使用并且可以进行安装的。从一开始遭遇安装失败, 陷入依赖噩梦, 而后一路前行, 最终达成了平稳的 PyPI 发布, 进而赢得了用户的信任。我所学到的那些宝贵经验, 也就是明智地去管理依赖, 先在本地进行测试, 还有使用, 采用.toml, 以及自动化发布流程, 这些彻底改变了我分发项目的方式。假设你此刻也已然开启了你的那一场打包行程, 那么务必要做好心理方面的接纳准备, 因为这极有可能会存在些许的“痛感”。然而一旦你熟练把控住了整个流程, 你便会亲身领略到身为一名开发者最为激动人心的时刻之一: 亲眼目睹着你的作品从你那台笔记本电脑出发, 一路迈向成千上万用户的手中。核心要点结语从“我”的代码到“我们”的工具借助这八个至关重要的关键经验, 我期望你可以躲开我往昔所踩过的那些坑, 更为顺畅地达成你那打包与分发的旅程。从一个仅在自身电脑上运行的脚本, 转变为一个能够被社区广泛运用的工具, 这不单单是技术层面的进步, 更是心态方面的转变。当你把代码进行打包, 而后发布至 PyPI 的时候, 你并非仅仅是在分享一个文件, 你乃是在为整个生态系统贡献力量。你正把你的智慧以及劳动, 转变为其他人能够依赖且使用的基石。怀着盼望, 我的这些经历能够对你有所协助, 促使你的代码切实迈向更为广阔的天地, 使得更多人能够从中获取福利。
返回列表