想象一下,您希望在Python中开发一个非平凡的最终用户桌面(而不是Web)应用程序.构建项目文件夹层次结构的最佳方法是什么?
理想的功能是易于维护,IDE友好,适用于源代码控制分支/合并,以及易于生成安装包.
特别是:
你把源头放在哪里?
你把应用程序启动脚本放在哪里?
你把IDE项目放在哪里?
你在哪里进行单位/验收测试?
你在哪里放置非Python数据,如配置文件?
你在哪里为pyd/so二进制扩展模块放置非Python源代码如C++?
S.Lott.. 350
没关系太重要了.无论什么让你快乐都会奏效.没有很多愚蠢的规则,因为Python项目可以很简单.
/scripts
或者/bin
用于那种命令行界面的东西
/tests
为了你的测试
/lib
为您的C语言库
/doc
对于大多数文档
/apidoc
对于Epydoc生成的API文档.
顶级目录可以包含README,Config和whatnot.
很难选择是否使用/src
树.Python没有区别/src
,/lib
和/bin
如Java或C具有.
由于/src
某些人认为顶级目录没有意义,因此您的顶级目录可以是应用程序的顶级体系结构.
/foo
/bar
/baz
我建议将所有这些放在"我的产品名称"目录下.因此,如果您正在编写一个名为的应用程序quux
,则会命名包含所有这些内容的目录 /quux
.
PYTHONPATH
然后,另一个项目可以包括/path/to/quux/foo
重用QUUX.foo
模块.
在我的情况下,因为我使用Komodo Edit,我的IDE cuft是一个.KPF文件.我实际上把它放在顶级/quux
目录中,并省略将其添加到SVN.
没关系太重要了.无论什么让你快乐都会奏效.没有很多愚蠢的规则,因为Python项目可以很简单.
/scripts
或者/bin
用于那种命令行界面的东西
/tests
为了你的测试
/lib
为您的C语言库
/doc
对于大多数文档
/apidoc
对于Epydoc生成的API文档.
顶级目录可以包含README,Config和whatnot.
很难选择是否使用/src
树.Python没有区别/src
,/lib
和/bin
如Java或C具有.
由于/src
某些人认为顶级目录没有意义,因此您的顶级目录可以是应用程序的顶级体系结构.
/foo
/bar
/baz
我建议将所有这些放在"我的产品名称"目录下.因此,如果您正在编写一个名为的应用程序quux
,则会命名包含所有这些内容的目录 /quux
.
PYTHONPATH
然后,另一个项目可以包括/path/to/quux/foo
重用QUUX.foo
模块.
在我的情况下,因为我使用Komodo Edit,我的IDE cuft是一个.KPF文件.我实际上把它放在顶级/quux
目录中,并省略将其添加到SVN.
根据Jean-Paul Calderone的Python项目的Filesystem结构:
Project/ |-- bin/ | |-- project | |-- project/ | |-- test/ | | |-- __init__.py | | |-- test_main.py | | | |-- __init__.py | |-- main.py | |-- setup.py |-- README
这篇由Jean-Paul Calderone撰写的博客文章通常作为Freenode上#python的回答.
Python项目的文件系统结构
做:
将目录命名为与项目相关的内容.例如,如果您的项目名为"Twisted",请为其源文件命名顶级目录
Twisted
.执行发布时,应包含版本号后缀:Twisted-2.5
.
Twisted/bin
如果有的话,创建一个目录并将可执行文件放在那里..py
即使它们是Python源文件,也不要给它们扩展.除了导入和调用项目中其他地方定义的main函数之外,不要在其中添加任何代码.(轻微的皱纹:因为在Windows上,解释器是通过文件扩展名选择的,你的Windows用户实际上确实需要.py扩展名.所以,当你打包Windows时,你可能想要添加它.不幸的是,没有简单的干扰技巧我知道要自动化这个过程.考虑到在POSIX上.py扩展只是一个疣,而在Windows上缺少是一个实际的错误,如果你的用户群包括Windows用户,你可能想要选择只有.py到处扩展.)如果您的项目可以表示为单个Python源文件,那么将其放入目录并将其命名为与项目相关的内容.例如,
Twisted/twisted.py
.如果您需要多个源文件,请改为创建一个包(Twisted/twisted/
,使用空Twisted/twisted/__init__.py
)并将源文件放入其中.例如,Twisted/twisted/internet.py
.将您的单元测试放在包的子包中(注意 - 这意味着上面的单个Python源文件选项是一个技巧 - 您总是需要至少一个其他文件用于您的单元测试).例如,
Twisted/twisted/test/
.当然,让它成为一个包Twisted/twisted/test/__init__.py
.将测试放在像Twisted/twisted/test/test_internet.py
.如果你感觉很好,分别添加
Twisted/README
并Twisted/setup.py
解释和安装你的软件.
别:
将您的源放在名为
src
或的目录中lib
.这使得在没有安装的情况下很难运行.把你的测试放在你的Python包之外.这使得难以针对已安装的版本运行测试.
创建一个只包含a
__init__.py
然后将所有代码放入的包__init__.py
.只需制作一个模块而不是一个包,它就更简单了.尝试提出神奇的黑客攻击,使Python能够导入您的模块或包,而无需用户将包含它的目录添加到其导入路径(通过PYTHONPATH或其他一些机制).您将无法正确处理所有情况,当您的软件无法在其环境中工作时,用户会对您生气.
查看正确开源Python项目.
让我摘录一下这篇优秀文章的项目布局部分:
设置项目时,布局(或目录结构)非常重要.合理的布局意味着潜在的贡献者不必花费永远寻找一段代码; 文件位置很直观.由于我们正在处理现有项目,这意味着您可能需要移动一些东西.
让我们从顶部开始吧.大多数项目都有许多顶级文件(如setup.py,README.md,requirements.txt等).每个项目应该有三个目录:
包含项目文档的docs目录
以项目名称命名的目录,用于存储实际的Python包
两个地方之一的测试目录
在包含测试代码和资源的包目录下
作为独立的顶级目录为了更好地了解文件的组织方式,这里是我的一个项目布局的简化快照,sandman:
$ pwd ~/code/sandman $ tree . |- LICENSE |- README.md |- TODO.md |- docs | |-- conf.py | |-- generated | |-- index.rst | |-- installation.rst | |-- modules.rst | |-- quickstart.rst | |-- sandman.rst |- requirements.txt |- sandman | |-- __init__.py | |-- exception.py | |-- model.py | |-- sandman.py | |-- test | |-- models.py | |-- test_sandman.py |- setup.py
如您所见,有一些顶级文件,一个docs目录(生成的是sphinx将生成文档的空目录),一个sandman目录和一个sandman下的测试目录.
"Python Packaging Authority"有一个示例项目:
https://github.com/pypa/sampleproject
它是一个示例项目,作为Python Packaging用户指南的包装和分发项目教程的辅助手段.
尝试使用python_boilerplate模板启动项目.它主要遵循最佳实践(例如这里的最佳实践),但如果你发现自己愿意在某个时刻将你的项目分成多个鸡蛋(并且相信我,除了最简单的项目之外的其他任何东西,你都愿意的话).常见的情况是你必须使用其他人的库的本地修改版本.
你把源头放在哪里?
对于规模较大的项目,将源分成几个蛋是有意义的.每个鸡蛋都将作为一个单独的setuptools布局PROJECT_ROOT/src/
.
你把应用程序启动脚本放在哪里?
理想的选择是将应用程序启动脚本注册为entry_point
其中一个鸡蛋.
你把IDE项目放在哪里?
取决于IDE.他们中的许多人将他们的东西保留PROJECT_ROOT/.
在项目的根目录中,这很好.
你在哪里进行单位/验收测试?
每个鸡蛋都有一组单独的测试,保存在其PROJECT_ROOT/src/
目录中.我个人更喜欢py.test
用来运行它们.
你在哪里放置非Python数据,如配置文件?
这取决于.可以有不同类型的非Python数据.
"资源",即必须打包在鸡蛋中的数据.这些数据进入相应的egg目录,位于包命名空间内的某个位置.它可以通过pkg_resources
包使用.
"配置文件",即非Python文件,它们被视为项目源文件的外部文件,但在应用程序开始运行时必须使用某些值进行初始化.在开发过程中,我更喜欢保留这些文件setuptools
.对于部署,可以有各种选项.在Windows importlib.resources
上,可以在Linux PROJECT_ROOT/config
或Linux上使用%APP_DATA%/
.
生成的文件,即在执行期间可由应用程序创建或修改的文件.我希望/etc/
在开发/opt/
期间和Linux部署期间保留它们.
你在哪里为pyd/so二进制扩展模块放置非Python源代码如C++?
成 PROJECT_ROOT/var
文档通常会进入/var
或PROJECT_ROOT/src/
(这取决于您是否将某些鸡蛋视为单独的大型项目).一些额外的配置将在PROJECT_ROOT/doc
和等文件中PROJECT_ROOT/src/
.
根据我的经验,这只是一个迭代问题.将您的数据和代码放在您认为的任何地方.机会是,你无论如何都会错.但是一旦你更好地了解事情将如何形成,你就可以做出更好的猜测.
至于扩展源,我们在trunk下有一个Code目录,其中包含python的目录和各种其他语言的目录.就个人而言,我更倾向于下次尝试将任何扩展代码放入自己的存储库中.
话虽如此,我回到最初的观点:不要做太大的交易.把它放在似乎适合你的地方.如果你发现一些不起作用的东西,它可以(而且应该)改变.
使用setuptools中的package_data
支持,非python数据最好捆绑在Python模块中.我强烈建议使用命名空间包创建多个项目可以使用的共享命名空间,这与将包放入(并且能够拥有共享命名空间)的Java约定非常相似.com.yourcompany.yourproject
com.yourcompany.utils
重新分支和合并,如果你使用一个足够好的源控制系统,它将处理合并,即使通过重命名; Bazaar特别擅长这一点.
相反,这里的一些其他的答案,我+1上有一个src
目录的顶层(与doc
和test
目录旁边).文档目录树的具体约定将根据您使用的内容而有所不同; 例如,Sphinx有自己的快速启动工具支持的约定.
请利用setuptools和pkg_resources; 这使得其他项目更容易依赖于代码的特定版本(如果您正在使用,则可以使用不同的非代码文件同时安装多个版本package_data
).