译者序
“Talk is cheap, show me the code”(空谈无益,代码为证)。程序员始终追求优雅的代码和规范的注释。但现实往往令人失望,通常是好不容易在GitHub找到了源码,却发现没有注释、说明文档和接口文档,这让很多人望而却步。在安装他人发布的软件包时,也时常会遇到莫名其妙的报错,费尽周折也找不到解决之道,在项目GitHub主页上也找不到合适的解决方案。这是很多从业人员不得不面对的现实问题。
那么,在发布自己的软件包以及对应的技术文档时,是否有工具可用?文档撰写是否有一定的标准呢?严格来说,不同语言的软件包发布通常涉及多个工具,技术文档也缺乏强制标准。然而,行业内已形成共识,程序员应遵守一些基本的规范和约定。
本书是一本关于Python打包与发布的工具书,旨在手把手指导读者完成整个软件包的创建过程,包括维护测试套件、自动化代码质量、持续集成、编写与维护文档、构建社区和更新代码。一眼望去,整个流程漫长而又烦琐,你甚至还会在读完全书后感慨发布工具之多。的确,发布自己的软件包并构建技术社区,是一件任重道远但又极具价值的事。
要做好这件事,首先,要对技术抱有极大的热情,具有奉献精神;其次,要在自己发布软件包的相关领域持续跟进和集成;最后,甚至要成为一个兜售者,热情地为技术会议上的每个同行介绍自己的软件包。有些人甚至会牺牲陪伴家人的时间和休息时间来全身心投入这项工作。这也许就是极客 (黑客 )精神的写照,一群热爱技术的人为了自己的行业孜孜不倦、持续努力。其实,计算机领域不乏
这样的人,如自由软件之父Richard Stallman、Linux之父Linus Torvalds、算法大师Donald E. Knuth,以及C++发明者 Bjarne Stroustrup。
发布自己的软件包,就像孕育自己的孩子一样,从无到有,由小到大。从第一行代码到一个庞大的社区,需要付出满腔热忱。当然,有人可能会说,既然这么累,为什么还要自己发布软件包,用他人发布的不好吗?或者参与开源项目不好吗?当然可以,参与开源项目、开源活动是一件很棒的事。如果你能够把自己在某一领域的成果以一个软件包的形式发布出来供大家使用,那更是一件令人骄傲的事。这并不是鼓吹你发布自己的软件包。但是如果你做到了,那一定既酷又炫!
无论是学术界科研人员还是产业界工程师,当技术积累到一定程度时,都会有发布自己软件包的需求,也会有与志同道合的人共同建设社区的需求。从学术角度来看,许多研究往往止步于理论构建、实验设计、编码实现与发表高水平的学术论文。很多人在论文发表后,便会转而去探索新的领域,导致论文永远沉睡于海量文献库里,很多同行无法将其中绝妙的研究复现到实际应用中,只能日复一日地熬夜加班重复攻克同样的问题。如果能够将此类成果梳理成软件包发布出来,并配有完整的技术文档,那么很多看到论文的读者便可以基于技术文档对其进行复现,同时工程师也可以基于论文和软件包对其进行工程化、产品化,最终落地产生商业价值。如果工程师能解决自己遇到的工程难题和各种问题或者以一个性能更佳、效率更高的软件包发布出来,那么对于技术领域来说便是一件值得庆幸的事。
本书内容主要包括4部分。第Ⅰ部分 (第 1~3章)介绍常见的打包工具,并对构建的文件进行详细的剖析;第Ⅱ部分 (第4~6章)讲解如何创建并测试可行的软件包;第Ⅲ部分 (第 7~9章)讲述了GitHub持续发布,以及技术文档的编写与维护;第Ⅳ部分 (第 10~11章)介绍 cookiecutter模板的使用和社区的构建。本书适合计算机科学家、企业工程师和对发布自己的 Python软件包感兴趣的人员阅读。
在翻译本书的过程中,我得到了李静老师的帮助,非常感谢她对本书进行细致审校。此外,我还要感谢清华大学出版社的编辑、校对和排版人员,感谢他们为了保证本书质量所付出的努力。
由于本书涉及内容广泛、深刻,加上译者翻译水平有限,书中难免存有不足之处,恳请各位读者不吝指正。
推荐序
每个人的 Python之旅都始于不同的起点。无论始于何处,我们都注定要逆流而上,体验别样的风景和聆听不同的声音。随着学习的深入,如同河道变窄,树木愈发茂密,你甚至会开始考虑如何向他人交付 Python应用程序。在河流的源头,你会在一个隐蔽洞穴的入口处发现一些破碎的项目外壳。在它们坠入深渊之前,你会突然听到一个洪钟般的声音质问道:“你最喜欢的打包工具是什么?”。
Python提供了适合各类开发者的工具,可以在 Python软件包索引(简称 PyPI,可访问链接 https://pypi.org)上找到。 PyPI在带来便捷的同时也引入了很多新挑战,因为你会开始关心安装、依赖项、环境以及与现实世界中使用软件相关的其他重要问题。这是创建和维护新开源软件包的核心,也是本书重点介绍和讨论的内容。
根据我的经验,大多数 Python书籍都很少提及软件包的打包。很多书籍都乐于从软件组织的角度讨论模块和软件包,甚至可能会附赠一个基本软件包的简单框架。然而,制作生产级可下载软件包的实际过程往往被“留作练习”。因此,本书应运而生,旨在解决这一特定的问题。
尽管大多数 Python用户可能并不倾向于发布公开软件包,但仍然经常需要向他人提供 Python代码,而这样做往往会面临相当大的挑战。这在很大程度上是生态系统复杂性导致的。 Python软件包通常不仅仅涉及 Python语言本身,还可能混合了 Python、C、C++、 Fortran和 Rust等多种编程语言。软件包需要在任何类型的操作环境 (如 Linux、Mac、Windows或更新的 Web Assembly)中运行。此外,还需要考虑处理多个 Python版本的兼容性问题、软件包的依赖性问题以及软件包管理工具不断变化的问题,这使得问题变得更加复杂。
在动手写这篇推荐序之前,我问了自己一个简单的问题 ——我能用这本书中的知识来更新自己的一些项目吗?我接触 Python已 25年多。在此期间,我只发布并维护了几个小软件包,而且一直都是兼职进行。老实说,我自己通常也在回避打包。这意味着,我最初是带着怀疑和保守的态度翻开此书的,对于软件包的“最佳实践”几乎毫无认知。
但令人欣喜的是,我从这本书中学到了很多。首先,这本书以完全现代的方式介绍了当前的打包工具。其次,它提供了大量与软件包开发有关的背景资料和问题,然后介绍了解决这些问题的实用方法。此外,我还学到了一些与我已经在使用的工具 (如 pytest、 coverage等)相关的新技巧。最后,你甚至还能找到关于创建和管理项目社区的建议。
综上所述,这并不一定是一本“简单”的书。即使采用了现代化的处理方式,打包仍然没有放之四海而皆准的方法。你可能会发现自己可以尝试的不同方法,并以自己的方式阅读这本书。我认为,关键是要保持开放的心态,把这本书当作一本实用指南,切实地明白一切皆有可能。这样做,便会发现本书是一个有用的灵感来源。
——Python Distilled作者, David Beazley(https://www.dabeaz.com)
自 序
2014年秋天,我开始在ITHAKA工作。那时,团队一直在不懈努力,力求摆脱一个专有内容管理系统的束缚,该系统的发布周期长达数月,因此很难进行项目的快速迭代更改。不过,这一努力获得了丰厚的回报,我们成功推出了一个新的交付平台,它与我们所追求的敏捷性能够完美契合。
前端团队选择使用Django Web框架,用于JSTOR平台(可访问链接https://www.jstor.org)上面向用户的全新开发,我的加入也与这一选择有关。该团队早期通过开发可独立安装的 Python软件包支持该项目,事实证明这很有帮助,因为这些包在实现产品多样化的同时还保留了核心共享功能。围绕内容和访问模型的业务领域非常复杂,而这些软件包为它们设定了有用的界限,并赋予了可重用性。尽管这一概念的方向很明确,但仍然存在一些不足之处。
当时,我们没有运行私有软件包仓库,因此所有软件包都必须从我们的版本控制系统中安装。我们没有进行语义化版本管理,仅依赖Git的提交哈希值也无法深入了解或管理不同版本之间的变化。我们没有维护更新日志,而是依靠提交消息来管理更改。
在随后的几年里,我们在Django和Python上的投入逐渐累积到数千行代码,为JSTOR的大部分流量提供服务。我们的软件包越来越大,数量也越来越多,打包过程中的摩擦也日益显现。将软件包与应用程序代码混杂在一起,虽然带来了立即反映更改的便利,但导致版本选择能力退化,逐渐形成了“哪里最方便,代码就放在哪里”的惯性模式。
当核心基础架构小组开始为私有打包提供一流的支持时,这一范式发生了转变。看到这一新功能,并对我们的组织结构进行审视后,我开始思考如何利用持续集成和标准化来保持敏捷性,同时提高质量,并重新获得版本选择的能力。
apiron项目(可访问链接https://github.com/ithaka/apiron)是采用新打包方法的首次尝试,现已成为ITHAKA第一个积极开发的供第三方使用的开源项目。随着打包工作流程的优势日益明显,我们广泛采用了这一流程。如今,ITHAKA的前端团队维护着20多个Python软件包,为同样数量的应用程序提供支持。
ITHAKA的使命是改善知识的获取方式,我希望本书能为此贡献一份力量,在某些方面帮你拓宽眼界,在另一些方面帮助你实现梦想。虽然这本书注重实用性,但我更希望你能从中获得一些理论和哲学工具,帮助你和你的团队在自动化和可重复流程方面大幅提升工作效率。期待你的不同观点——这是一个向创作者持续迭代的集体知识提供反馈的机会。我希望你能从中受益,并提出不同意见和批评。
如有任何问题、成功故事或争议,请随时通过pubpypack @danehillard.com联系我。
作者简介
Dane Hillard现任ITHAKA(一家致力于高等教育领域的非营利组织)的技术架构师。他经验丰富,曾为支持数百万用户的JSTOR研究平台构建应用架构。目前,他还对安全、松耦合系统和形式化方法感兴趣。
译者简介
郭涛,主要从事人工智能、智能计算、概率与统计学、现代软件工程等前沿交叉领域的研究工作。已出版多部译作,包括《深度强化学习图解》《机器学习图解》和《概率图模型原理与应用(第2版)》。
致 谢
本书的完成过程充满了挑战,如果没有 Python软件基金会和Python打包管理机构工作人员的全力支持,这本书是万万不可能完成的。感谢你们的努力,让Python打包领域的发展势头持续向上。我之所以能在这里汇聚知识和流程,全是因为我站在了巨人的肩膀之上。
我写第一本书时,有幸在一家高端家居用品店的后台拥有一间舒适的咖啡店作为写作场所。而本书则完全是在家中完成——大部分时候,我都是坐在搭档 Stefanie的桌子对面奋笔疾书。感谢你的冷静、善良以及各种诙谐打诨。如果我们能在我的拖延症和抱怨声中熬过疫情带来的幽居时光,也许有一天我们真的能一起征服全世界。
感谢 ITHAKA团队对学习、改进和创新的持续热情。你们精益求精、臻于至善的追求驱使我不断向前。
本书差点就夭折了。感谢我的内容编辑Toni Arritola和策划编辑Mike Stephens,是你们让我有了第二次尝试的机会。你们的鼓励和反馈确保了本书的顺利出版。
我要感谢技术编辑Al Krinker,感谢你不断追问我的写作初衷。这无疑提高了作品的影响力和清晰度。
感谢Marjan Bace和Manning团队的其他成员,是你们让这本书焕发生机,并将它送到有需要的人手中。
非常感谢那些在本书出版初期就投入精力并提供反馈意见的勇士们。你们为我指明了方向,让我少走了许多弯路。
致所有为本书付出辛勤努力的审稿人:Aleksei Agarkov、Cage Slagel、Clifford Thurber、Daniel Holth、David Cabrero Souto、David Cronkite、Delena Malan、Edgar Hassler、Emanuele Piccinelli、Eric Chiang、Ganesh Swaminathan、H.vard Wall、Howard Bandy、Jim Amrhein、Johnny Hopkins、Jose Apablaza、Joshua A. McAdams、Katia Patkin、Kevin Etienne、Kimberly L.Winston-Jackson、Larry Cai、 Laxman Singh Tomar、Marc-Anthony Taylor、Mathijs Affourtit、 Matthias Busch、Mike Baran、Miki Tebeka、Richard J. Tobias、Richard Meinsen、 Robert Vanderwall、 Salil Athalye、 Sriram Macharla、 Vasudevan Surendran、Vidhya Vinay、Vraj Mohan和 Zoheb Ainapore,你们的建议让本书日臻完善。
最后,我要感谢对本书产生过直接、间接或其他积极影响的所有人。我无法一一列出所有人的名字,如有遗漏,纯属疏忽,还望海涵。感谢 Ee Durbin、Dustin Ingram、Brett Cannon、Paul Ganssle、 Filipe Laíns、Bernát Gábor、.ukasz Langa、Sébastien Eustace、Thomas Kluyver、Donald Stufft、Simon Willison、Will McGugan、Dawn Wages、 Reuven Lerner、David Beazley、Brett Slatkin、Tzu-Ping Chung、Henry Schreiner、Pradyun Gedam、Paul Moore、Tushar Sadhwani、Sandi Metz、 Jason Coombs、Jeff Triplett、Carlton Gibson、Chris Kolosiwsky和 Peter Ung。
关于封面插图
本书封面上的图摘自Jacques Grasset de Saint-Sauveur于1797年出版的作品集。每幅插图都是手工精细绘制和上色的。
在那个时代,仅从人们的衣着打扮就很容易辨别出他们的居住地、职业或社会地位。 Manning以几个世纪前丰富多彩的地区文化为基础,精选此类藏品中的精美图片作为图书封面,旨在颂扬计算机行业的创造性和主动性。
关于本书
本书介绍了Python打包的几个特定方面,以及几乎适用于所有编程语言的若干核心概念,旨在提高团队和个人在软件交付方面的生产力。无论是DevOps团队、产品团队,还是站点可靠性团队,都能从中发现新的实践和工具来完善他们的工作。如果你希望尽可能多地实现 Python项目生命周期的自动化、标准化和编排,本书将是你的不二之选。
本书读者对象
本书适合已经熟悉Python并希望与朋友、团队或全世界分享代码的读者阅读。虽然本书是专门为个人的管理 (包括实践)而量身定制的,但其内容几乎可以扩展到任何规模的团队。协作是有效软件开发的关键,因此本书所介绍的实践倾向于消除烦琐枯燥的工作,让你可以专注于通过代码和技术文档进行有效的交流。
随着软件在科学界的不断发展,打包软件的价值也与日俱增。成功的开源项目在诸多里程碑式的事件中屡见不鲜,如登陆火星和黑洞成像。无论你是想追求创新,还是仅仅想确保实验室的负责人(PI)能够验证你用来生成结果的代码,可重复的过程都是至关重要的。
如果你以前没有使用过单元测试和lint等软件质量保障工具,本书将从基本概念入手,帮助你构建自动化质量体系,并帮助你将质量检查扩展为丰富的自动化套件。你可以把时间花在思考如何提前发现问题上,而不是疲于救火。
本书结构安排
本书共11章,分为4个部分。第Ⅰ部分介绍打包任何类型软件的内在价值。第Ⅱ部分引导你构建一个可正常运行的软件包,其中包含了软件包可能需要的各项功能。第Ⅲ部分介绍高度协作项目的自动化和维护需求。第Ⅳ部分展示如何重复这一过程,并扩展用户和贡献者群体。
第Ⅰ部分“基本概念”为Python打包奠定了基础,并通过涵盖以下方面,让用户在开始构建自己的软件包时拥有正确的心态。
第1章介绍了打包的起源,以及它在当今共享软件中仍然有价值的原因。通过这一章的学习可能会拓宽人们对软件包定义的理解,并发现软件包的目标受众非常广泛。
第2章介绍如何开始使用附录中的工具进行产品打包工作。
第3章展示 Python软件包的基本含义,包括所涉及的文件和元数据,以及它们是如何在整个过程中流动的。
第Ⅱ部分“创建可行的软件包”将把最小Python软件包扩展成一个具有实际行为的包,你可以在完成本书的学习后进一步扩展它。
第4章讲解如何将第三方依赖、命令行界面和非Python扩展整合到软件包中。
第5章介绍用于编排单元测试活动的单元测试工具,以确保软件行为的质量。
第6章在质量的基础上更进一步,纳入了对常见错误、类型安全和代码格式一致性的检查。
第Ⅲ部分“让软件包走进公众视野”推荐了一些可以在任何地方采用的实践,这些实践对于与他人协作尤其有用。
第7章展示自动化和持续集成原则的力量,帮助你思考如何为贡献者创建严谨的反馈回路。
第8章介绍文档的重要性,并展示如何集成一个涵盖代码和文档说明的自动化文档构建系统。
第9章介绍了如何以最小的代价定期更新 Python软件包,从而避免积累技术债务。
第Ⅳ部分“路漫漫其修远兮”回答了在掌握新技能后,下一步该怎么走的问题。
第10章旨在将在前几章中学到的实践转换为可复用的项目模板,以便在未来的项目中使用。
第11章旨在分享一些实践方法,帮助你在项目中构建一个由用户、贡献者和维护者组成的社区,此类社区将在前几章所述的清晰流程的基础上蓬勃发展。
我建议从头到尾顺序阅读本书。书中的每一章都是在前一章的基础上逐步展开的,每一步都有每一步的收获。此外,本书附录讲解了如何安装工具,根据我的经验,这些工具会让打包工作变得更有趣。
附录A中提及的工具,可以让你更轻松地安装多个版本的 Python(和其他语言 )以及调用打包过程中创建的各种 Python解释器和虚拟环境。
附录B中提及的工具与项目没有太大关系,但可以提高你在大多数 Python项目中的工作效率。
关于代码
本书包含许多源代码示例,既有带编号的代码清单,也有普通文本。在这两种情况下,源代码的格式都采用等宽字体,以便与普通文本区分开来。有时,代码也以粗体显示,以突出改动的代码,例如,在现有代码行中添加新功能时。
在许多情况下,原始源代码都经过了重新格式化;添加了换行符,并重新调整了缩进,以适应图书排版。在极少数情况下,因为部分代码过长,还在代码行中添加了换行标签 (.)。此外,在正文描述代码时,往往会删除源代码中的注释。
书中的源代码可在 GitHub上找到,网址为http://mng.bz/69A5,也可通过扫描本书封底的二维码下载。
每一章配套的代码都严格地与该章结束时软件包的完整状态保持统一。我非常审慎地做出了以上选择——因为打包配置需要在许多文件中使用精准的语法和数值,它甚至比常规编程更难做到正确无误。为了最大限度地减少挫败感,我认为与按代码清单组织代码相比,这是最好的参考方式。
由于打包实践会随时间发生变化,我将陆续提供本代码配套的更新版本。为避免混淆,我会将这些更新版本与本版的代码区分开来,并在配套的代码资源中提供相应的链接。