创建成功的Python项目

jopen 12年前
     <blockquote>     <p>创建一个成功的开源 Python 项目所涉及的并不仅仅是编写有用的代码,与其相关的还有社区的参与、越来越多的合作机会、技艺以及支持等。探索最佳的做法有助于你创建出自己的成功项目。</p>    </blockquote>    <p> 开源 Python 项目的生态系统丰富多样,这使得您能够站在巨人的肩膀上来开发下一个开源项目。此外,这意味着存在一系列的社区规范和最佳做法,通过遵守这些约定并把这些做法应用到项目中,你可以为自己的软件赢得更广范围的采用。</p>    <p> 本文涵盖了一些在构建大型和小型的项目时都运作得很好的实践做法,这些项目都已经赢得了广泛的用户群体。这里给出的这些建议的都是合理的、有其意义的,不过,因为结果可能会有所不同,所以不必把它们当成严格的教条来遵守。</p>    <p> 首先我们来讨论一下,解耦的过程如何能够带来一个更强健的社区,在编写、维护和支持开源软件等各方面都带来更大的生产能力。</p>    <p><strong> 合作(collaboration)和互助(cooperation)的对比</strong></p>    <p> 在 DjangoCon 2011 大会期间,David Eaves 作了基调发言,雄辩地表达了这样的想法,即尽管合作(collaboration)和互助(cooperation)有着类似的定义,但还是有着细微的差别:</p>    <p> “我认为,和作(collaboration)不同于互助(cooperation),其需要项目涉及到的各方通力来解决问题。”</p>    <p> Eaves 接着又给出了一整篇文章,专门说明 GitHub 如何成为革新开源的运作方式——特别是在社区管理方面的运作方式的推动力。在“How GitHub Saved OpenSource”这篇文章(参见参考资料)中,Eaves 说到:</p>    <p> “我相信,当捐献者能够以低交易成本的互助方式来参与,并且高交易成本的合作尽可能的少时, 开源项目的运作能达到最好。开源的高明之处就在于其不需要一个工作组来共同讨论每个问题以及解决问题,而是恰恰相反。”</p>    <p> 他接着谈到了分支(forking)的价值所在,以及其如何通过在参与者之间启用低成本的互助来降低合作的高成本,这些参与者能够在无需批准的情况下推进项目。这种分支把需要的合作搁置起来,直到解决方案已经做好了合并的准备为止,如此来支持更快速的动态的实验。</p>    <p> 你可以以类似的方式来打造自己的项目,目标是相同的:在编写、管理和支持项目的整个期间,增加低成本的互助,同时尽可能减少代价高昂的合作。</p>    <p><strong> 编写</strong></p>    <p> 从一张白纸开始,创建一些新鲜的东西,制造一些有创意的东西——或仅仅是一些与现有的略不同的东西,没有什么事情比得上启动一个新的项目并和全世界分享你的努力成果让人感觉更好的了。</p>    <p> 与维护不同,在编写代码时,你是在创造新的东西而不是在修改或是修正已有的东西。编写和构思一个项目除了是一门科学之外还是一种艺术形式,其他人会看到实现的情况并会对代码的质量作出判断,而你的名字将会永远和它连在一起。</p>    <p> 因此。了解工匠的心态以及据此来编写软件的方法是很重要的。编写新的项目不仅仅是意味着生成代码:项目的创建和构思包括了编写有着精美风格的让人乐于阅读的代码、在适当的时候为验证项目中的功能创建测试代码,以及制作详尽的有帮助的文档。</p>    <p><strong> 技艺</strong></p>    <p> 工艺(craft)一般是指艺术行业或是职业需要特殊的技能来手工制作一些东西,通常是小规模生产的物理器件。就软件工匠关注的更多的是质量而非数量这一意义而言,你可以延伸这一定义,把它应用在软件上。</p>    <p> 对于工匠来说,产品具有吸引力而非只是功用是很重要的。具体来说,在软件中,工匠要努力确保代码的干净和美观、应用编程接口(API)的悦目,以及文档和测试用例能够给用户带来是在使用坚实的产品进行工作的这种感受。</p>    <p> 在这种心态下工作,对于心灵来说是一种奖赏,也是在制作开源软件时能感受到诸多享受的原因:你不再受困于回应最后期限、客户以及其他的外部需求,而是按照自己的时间来,享受制作一些美好事物的乐趣。</p>    <p><strong> 代码风格和规范检查</strong></p>    <p> Python 的增强建议(Python Enhancement Proposal,PEP)8(参见参考资料)是一个详细的 Python 风格指南,你应该基于该指南来建立自己的 Python 项目(或至少是基于你的项目的风格指南)。不是非要教条地采用 PEP 8,不过你的工作成果越接近 PEP 8 规范,其他的 Python 开发者就越容易提交以标准的 Python 社区风格实现的整洁的补丁包。</p>    <p> 除了风格的一致性之外,在捕捉诸如缺失导入和未定义变量一类的错误方面,代码规范(linting)的概念也是很有作用的。除了风格检查器会帮助你进行检查,找出违背了默认规则或是自定义规则的代码之外,现还有一些规范器(linter)或是一些工具,最常用到的一些实用程序是:</p>    <p> 1. pyflakes</p>    <p> 2. pylint</p>    <p> 3. pep8</p>    <p> 请参阅参考资料获得到这些工具的链接。</p>    <p> 无论你选择遵从的是哪一种约定,如果这些约定偏离了 PEP 8 的话,我建议文档化它们,以便让那些想要为你的项目做贡献的人了解你所采用的编码风格,显式的说明要好于隐含不语。</p>    <p> pyflakes 是一个特别有用的规范器,它很好地平衡了有用的功能、捕捉和标出错误这两方面,不会过度地揪住微小的古怪做法不放。下面是一个在某个 Python 项目上使用 pyflakes 的示例会话:</p>    <blockquote>     <p>$ pyflakes kaleo</p>     <p>kaleo/forms.py:1: 'form' imported but unused</p>     <p>kaleo/forms.py:4: undefined name 'forms'</p>     <p>kaleo/forms.py:6: undefined name 'forms'</p>    </blockquote>    <p> 立刻,该工具告诉了我有一个 import 的输入错误,查看文件 kaleo/forms.py,我发现:</p>    <blockquote>     <p>from django import form</p>     <p>class InviteForm (forms.Form):</p>     <p>email_address = forms.EmailField ()</p>    </blockquote>    <p> 从内容中可看出来,要把第 1 行改为 from django import forms。</p>    <p><strong> 测试</strong></p>    <p> 在项目中提供验证代码有效性的测试始终是一件好事,以此来防止回归被忽视,以及在某些情况下作为一种文档形式,通过阅读其中的测试代码可以让其他人知道你的库 API 是如何工作的。</p>    <p> 话虽如此,但我不会根据项目是否包括测试用例或是完成这些测试的方式来判断项目的完整性或可行性。测试用例的存在并不能保证代码的质量,这可能是一个有争议的观点,但我相信,完全没有测试比去测一些错误的东西要来得好一些。在编写测试代码时,考虑为每个测试单元给出各种输入是一件很重要的事情。</p>    <p><strong> 文档</strong></p>    <p> 不过,与测试不同的是,你可以根据项目文档的质量和广博性来判断项目的质量和技艺水平。用与创作和维护代码相同的方式来创作和维护稳定,编写良好的并且是有深度的文档会鼓励捐献者效仿你的做法,使你的项目变得更易于为用户接受。</p>    <p> 使用诸如 Sphinx 和 Read the Docs 一类的工具(参见参考资料),你可以发布及时更新的、外观极为不错的文档。使用这些工具是一件简单的事情,也就是写一些文字内容并并推送提交。习惯于尽可能地使用 commit 来提交文档的变更是很适当的一种做法。</p>    <p><strong> 维护</strong></p>    <p> 在 Python Package Index(PyPI)上发布了第一个版本,并通过各种 Tweet 消息和博客文章公布该版本的消息,开始有了一些使用者之后,你就需要在任何后续的创作活动中加入维护方面的考虑了。用户会报告错误、要求添加功能、提一些文档中没有明显涉及到问题,诸如此类等等。</p>    <p> 有些事情你会选择不去处理,给出一些权变措施;但其他的一些问题,你会打算或是修正文档或是修正代码。使用诸如 git 一类的分布式版本控制系统(distributed version control system,DVCS)并常常发布开发者包,这种做法可以大大简化维护工作,使之变成一件不再是烦人的事情。</p>    <p><strong> 源控制</strong></p>    <p> 有许多可用的 DVCS,其中就包括了 git 和 mercurial(参见参考资料),无论你选择的是哪一个控制系统,请确保它提供了源控制功能,这种功能赋予你这样的能力,可以让用户分支你的项目,然后自己来解决其中的错误。</p>    <p> 进行变更的速率取决于许多因素,一个关键的因素是目标受众(例如,其他开发者、非技术型的最终用户)。如果你的项目是针对开发者来编写的,那么鼓励通过拉请求(pull request)来报告错误或是请求功能之类的做法可以真正地做到降低维护者的负担。这种做法还提升了社区的归属感,因为大家都把他们的捐献合并到了将来的版本中。</p>    <p><strong> 开发构建</strong></p>    <p> 你会希望尽早地以及经常性地发布开发版本,在每次有一组附加的补丁包出来之后都会发布版本,如此多次。这会让其他在工作中使用你的项目的开发者能够更容易地针对项目中的最新更改来运行。越多的人在不同的情况下使用这些代码,那么一旦到发布一个新的稳定版本的时候,该版本就会有越高的质量。</p>    <p><strong> 支持</strong></p>    <p> 支持是和维护相随的,参与并构建一个由用户和捐献者组成的社区至关重要。赋予其他人通过支持来帮助你的权利,你就是在增强项目的全面合作因素,在项目的规模方面提供更好的伸缩性,以及自然而然地增加了解决用户问题的做法。</p>    <p> 为了达到该目的,请确保提供多种渠道来增加接触的机会,让用户更加容易地与你接洽以及参与到项目中。可选的沟通渠道包括 IRC、邮件列表以及诸如 推ter 一类的社交媒体汇聚点。</p>    <p><strong> IRC</strong></p>    <p> 在诸如 freenode 一类的 IRC 平台上设置一个沟通频道是一个好主意,我就为自己的项目设置了一个:nashvegas;除了我之外只有一个用户,虽然这种情况很少有,但我的 IRC 客户端还是悄无声息地运行在后台。当偶尔有用户提问时,我能够只花很少的交易成本就以一种比通过邮件要动态得多的方式来做出响应。</p>    <p><strong> 邮件列表</strong></p>    <p> 对于大多数的开源项目来说,有一个用于支持的邮件列表并在捐献者之间讨论开发进程是一种标准的做法。我的建议是,把支持放在一个邮件列表中,只有在内容已经变得太多,彼此影响到了各小组的讨论的时候,才把它分成“用户”列表和“开发”列表。</p>    <p><strong> 推ter</strong></p>    <p> 为项目开设一个 推ter 帐户,大家可以在这里与你快速地讨论工作。推ter 帐户还是一个可以作为发布项目消息的好地方。</p>    <p><strong> 结束语</strong></p>    <p> 给 Python 社区中的开源软件编写并捐献代码是一种有趣且有益的体验。在增加低成本互助机会的同时侧重于减少高成本的合作,这种做法有助于项目与活跃的捐献者一起成长。在开源领域,就你的项目来说,你有大把的自由来成为一个能工巧匠,充分利用这一点并享受它。把关注的重点放在一致的代码风格、坚实的测试和编写良好的文档上,以此来提高项目被用户和其他开发者采用的几率。此外,要利用 DVCS,关注拉请求,经常性地发布开发版本。最后还有一点就是,你可以提供多种支持渠道,以及允许社区协助你提供这种支持,通过这些做法来进一步提升项目的采用率并促进项目的成长。</p>    <p> <strong> 学习资料</strong></p>    <p> 1. 阅读 Mark Pilgrim 的 <a href="/misc/goto?guid=4958327746890421838" target="_blank">Dive into Python</a>,获取关于该语言的一个介绍。</p>    <p> 2. 欲了解更多关于打包 Python 项目方面的信息,可以读一下 <a href="/misc/goto?guid=4958327747694818389" target="_blank">A guide to Python packaging</a>(Patrick Altman,developerWorks,2011年 10 月)这篇文章。</p>    <p> 3. 阅读更多 David Eaves 的博客文章: <a href="/misc/goto?guid=4958327748500887056" target="_blank">Wikis and Open Source: Collaborative or Cooperative?</a> 和 <a href="/misc/goto?guid=4958327749289865600" target="_blank">How GitHub Saved OpenSource</a>.</p>    <p> 4. 在潜心进行下一个 Python 项目之前,请确保已了解 PEP 8,Python 代码的这一“官方”风格指南。</p>    <p> 5. 浏览一下我的项目 <a href="/misc/goto?guid=4958327750083698742" target="_blank">nashvegas</a> 的 GitHub 页面,以此来做为一个使用 DVCS 的 Python 项目的例子。</p>    <p> 6. 看一看 <a href="/misc/goto?guid=4958327750885143630" target="_blank">PyPI</a>。</p>    <p> 7. 了解更多关于<a href="/misc/goto?guid=4958327751681329834" target="_blank">分布式 Python 模块</a>方面的内容。</p>    <p> 8. <a href="/misc/goto?guid=4958327752474562202" target="_blank">developerWorks 开源专区</a>提供了丰富的关于开源工具和使用开源技术方面的信息。</p>    <p> 9. 在 推ter 上关注 <a href="/misc/goto?guid=4958327753271175439" target="_blank">developerWorks</a>。</p>    <p> 10. 在 <a href="/misc/goto?guid=4958327754060253584" target="_blank">Easy and beautiful documentation with Sphinx</a> (Alfredo Deza,developerWorks,2011年 11 月)一文中了解更多关于 Sphinx 的内容。</p>    <p> 获取产品和技术</p>    <p> 1. 有许多可用的规范器,常见的选择包括了 <a href="/misc/goto?guid=4958327754854451830" target="_blank">pyflakes</a>、<a href="/misc/goto?guid=4958327755657591267" target="_blank">pylint</a>,以及 Python 风格指南检查器 <a href="/misc/goto?guid=4958327755657591267" target="_blank">pep8</a>。</p>    <p> 2. 在准备往项目中加入文档的时候,一些在线的工具可把这一工作变得更容易一些。两种这样的工具选择是 <a href="/misc/goto?guid=4958327757170485181" target="_blank">Sphinx</a> and <a href="/misc/goto?guid=4958327757971772003" target="_blank">Read the Docs</a>。</p>    <p> 3. <a href="/misc/goto?guid=4958183577944756424" target="_blank">git</a> 和 <a href="/misc/goto?guid=4958189470451666395" target="_blank">Mercurial</a> 都是非常棒的 DVCS。</p>    <p> 讨论</p>    <p> 1. 看看一些 developerWorks 博客文章,帮助在 developerWorks 社区中建立 <a href="/misc/goto?guid=4958327760228428355" target="_blank">Real world open source</a> 组。</p>    <blockquote>     <p>关于作者</p>     <p>Patrick Altman 是 Pinax 的一位核心开发者,其创建并为其他的许多开源项目贡献了自己的力量。现在是 Engineering at Eldarion 的 VP。在这之前,他是 StudioNow 的首席软件工程师(Principal Software Engineer),该公司后来被出售给了 AOL。目前他和妻子及三个孩子居住在田纳西州的 Nashville。</p>    </blockquote>    <div id="come_from">     来自:     <a id="link_source2" href="/misc/goto?guid=4958327761030828936" target="_blank">译言</a>    </div>