开源Python项目结构
思考
当开始一个Python项目,我的意思是不仅仅是快速脚本的拼凑,而是作为一个产品化的程序,如何组织代码和文档,是需要精心考虑的。参考成熟的开源项目编程风范,使自己的程序能够不断迭代优化,是需要从开始就做好规划的。
工具和概念
以下是开发Python项目的工具和概念,可以帮助我们更好组织项目,编写更清晰的代码:
项目层次(目录结构)
setuptools
和setup.py
文件git版本控制
使用GitHub管理项目
GigHub的"Issues"用于以下功能:
bug跟踪
功能需求
未来计划
发布/版本管理
git-flow实现git工作流
py.test实现单元测试
tox实现测试标准化
Sphinx用于自动生成HTML文档
TravisCI用于持续测试集成
ReadTheDocs用于持续文档集成
Cookiecutter用于将上述步骤自动化以启动下一个项目
项目层次(目录结构)
当设置一个项目,layout
(或称为目录结构)是正确开始的重要步骤。一个恰当的项目层次意味着潜在的代码贡献者不必浪费时间找寻代码片段,凭直觉就能找到文件。
大多数项目都有一些顶层文件(类似setup.py
, README.md
, requirements.txt
等),然后有3个目录是每个项目都具备的:
docs
目录包含项目文档一个和项目名称相同的目录存储实际的Python包
一个
test
目录位于2个位置:在包目录下的
test
目录包含测试代码和资源以及一个顶层的独立目录
以下是一个简单的sandman
项目(注:这里采用了Open Sourcing a Python Project the Right Way文档中案例)
上述,有一个docs
目录(其中generated
目录是一个空目录,sphinx将生成的文档存放在这个目录中),有一个sandman
目录,以及在sandman
目录下的test
子目录。
setuptools
和setup.py
文件
setuptools
和setup.py
文件setup.py
文件类似于其他通过diskutils
包来使用其他包用于安装Python包。它是任何项目一个非常重要的文件,因为它包含了在PyPI中使用的版本信息,软件包环境需求,项目描述,以及你的名字和联系信息等等。这个文件使得软件包能够以一种程序化的方法被搜索和安装,提供了元数据和介绍工具。
setuptools
包(实际上是diskutils
的一个增强)将构建和分发Python软件包进行了简化。一个Python软件包可以通过setuptools
打包并且和diskutils
打包几乎完全一样。所以没有理由不使用setuptools
。
setup.py
位于项目的根目录。最重要的setup.py
部分称为setuptools.setup
,也就是包含了包的所有元信息部分。
以下是完整sandman项目的setup.py
快速脚手架工具cookiecutter
cookiecutter
cookiecutter 提供了一个快速创建模版的工具
然后执行
会提示一些问题,然后为你创建好目录结构及相应文件
README.md
文件可以通过pandoc来自动生成README.rst
是正确开始的重要步骤。一个恰当的项目层次意味着潜在的代码贡献者不必浪费时间找寻代码片段,凭直觉就能找到文件。
详细使用setuptools
的方法参考Distributing Python Modules
源代码版本管理 - GitHub
使用git-flow来管理git工作流
建议使用 git-flow 分支模式。
develop
是最主要的工作分之,也是用于部署下一个发行版的分支代码。feature
分支是相当于功能分之并且还没有部署的版本通过创建
release
分支来更新master
主干
参考这篇来安装git-flow
在Mac平台有多种方法安装,我采用如下方法
然后执行以下命令将现有的项目迁移
使用默认参数,完成后会自动创建develop
和master
分支。
大多数工作都是在develop
分支,包含了所有完成的功能和bug fix用于发布;nightly builds或持续集成服务器将标记为develop
。
要开始一个新功能,使用
此时就会创建一个新的分支: feature/<feature name>
。此时commit就会在这个分支,当功能就绪准备发布产品,就会合并到develop,则使用如下命令
代码合并到develop
分支并且会删除掉feature/<feature name>
分支。
当准备发布产品时候,就从develop
分支创建release
分支。使用如下命令:
所有的完成并且准备发布功能的必须位于develop
,这样才能feature finish
。当创建了release分支,则可以发布代码。一些在release之后的小的bug fix则直接在release/<release number>
分支。如果已经解决并且没有bug则使用如下命令:
这就会合并releae/<release number>
回到master
和develop
分支。
hotfix
类似从master
分离出的feature
:如果你已经关闭了release
分支但是意识到有必不可少的修改需要发布,则从master
分离出hotfix
分支(在git flow release finish <release number>
之后)类似:
然后在修改完成后,执行
virtualenv
和virtualenvwrapper
virtualenv
和virtualenvwrapper
如果在一个服务器上有多个Python项目,每个项目有不同的依赖,可以使用virtualenv
来创建虚拟机的Python安装,这样site-packages
,distribute
和pip
将按照这个方式独立。pip install
将软件包安装到virtualeve
而不是系统的Python安装。在不同的virtualenv
之间切换是非常简单的一条命令。
virtualenvwrapper
是一个单独的工具,用于创建和管理virtualenv
:
安装完成后,需要将路径添加到环境中
创建虚拟化环境
在虚拟环境中,很容易生成requirements.txt
,因为pip
可以通过requirements.txt
和-r
参数安装任何项目依赖。要创建这个文件,执行以下命令
测试py.test
py.test
Python标准库unittest
包:nose和py.test。两者都扩展了unittest
来使得容易添加附加功能。
测试设置:
在test
目录下,创建一个名为test_<project_name>.py
文件,py.test
的测试目录机制就会讲任何test_
开头的文件作为一个测试文件(除非告诉它不怎么做)。
测试覆盖:
结合py.test
,我们使用Ned Batchelder的coverage工具。要执行这个,线执行pip install pytest-cov
。
使用Tox完成标准化测试
Python的一个项目维护问题是兼容性
。如果目标是支持Python 2.x和Python 3.x,则需要确保代码可以在指定平台正常工作。tox提供了"Pythong标准化测试":它能够创建一个完整的沙盒环境并安装你的软件包及其环境来进行测试。
tox
是通过.ini
文件:tox.ini
来配置的,非常容易设置,以下是一个最小化的tox.ini
:
通过在envlist
中设置py26
和py27
,tox
就可以知道需要针对哪种环境测试。并且tox
默认就支持多种环境,例如jython
和pypy
。
dpes
是软件包的依赖,甚至可以告诉tox
从一个替代的PyPI URL安装所有或部分依赖。最后,执行所有环境的检查
setuptools
集成
tox
可以集成到setuptools
这样python setup.py test
就可以运行tox
测试。以下代码片段是从tox
文档中摘录加入到setup.py
文件:
使用Sphinx撰写文档
Sphinx是从pocoo演化出来的工具,用于生成Python文档,从代码尽可能方便地自动生成HTML文档。
sphinx有一个类似javadoc
的扩展,称为autodoc
,可以从代码文档字符串中提取出reStructured文本。要能够充分使用Sphinx和autodoc
,需要格式化代码文档字符串以便使用Sphinx的Python directives。
以下是一个模块功能使用了
然后在项目根目录下执行
则会在docs
目录下创建Sphinx的文档,并创建构建html输出的脚本。然后进入docs
目录,创建输出
生成的文档输出到docs
目录下的_build/html/
子目录中
PEP 8
Jetbrains 默认支持PEP 8代码风格检查
缩进不符合规范
解决的方法有两种:
重新格式化代码(推荐):选择
Code
菜单,然后选择Reformat Code
就能够执行代码重新格式化,以符合标准。如果要修改通用的代码风格,例如每行缩进的空格数量,可以使用Code Style -> Python
,可以调整缩进成词,空格,回行,空白行。在设置中可以搜索pep
来关闭PEP8特定的设置。 - 参考 How to get rid of all the underlines that indicates a typo or too many spaces?忽略(不推荐):在任何提示信息的高亮代码行按下
Alt-Enter
,然后选择Ignore errors like this
,这样就会在pycodestyle.py
中加入W191到黑名单,忽略所有PEP8警告。 - 参考 get rid of PEP8 indentation warning in docstrings
函数名不符合规范
参考What is the naming convention in Python for variable and function names?
Python PEP8对于函数名和变量要求全部采用小写字母,单词间分隔采用下划线_
;只有在遗留代码中已经存在混合大小写命名情况才使用mixedCase。
要忽略已经存在的这种变量或函数大小写,可以采用类似前述处理缩进忽略方法,按下Alt-Enter
然后选择Ignore errors like this
。
另一种方法参考 function name should be lowercase,使用菜单File –>Settings–>Editor–>Inspections–>Python–>PEP 8 naming convention violation
参考
Last updated