想象一下,您希望在Python中开发一个非平凡的最终用户桌面(而非Web)应用程序。构建项目文件夹层次结构的最佳方法是什么?
理想的功能是易于维护,IDE友好,适用于源代码控制分支/合并,以及轻松生成安装包。
特别是:
答案 0 :(得分:340)
没关系太重要。无论什么让你快乐都会奏效。没有很多愚蠢的规则,因为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。
答案 1 :(得分:222)
根据Jean-Paul Calderone的Filesystem structure of a Python project:
Project/
|-- bin/
| |-- project
|
|-- project/
| |-- test/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- setup.py
|-- README
答案 2 :(得分:202)
此blog post by Jean-Paul Calderone通常在Freenode的#python中作为答案提供。
Python项目的文件系统结构
执行:
- 将目录命名为与项目相关的内容。例如,如果您的项目名为“Twisted”,请为其源文件
Twisted
命名顶级目录。执行发布时,应包含版本号后缀:Twisted-2.5
。- 创建目录
Twisted/bin
并将可执行文件放在那里,如果有的话。即使它们是Python源文件,也不要给它们.py
扩展名。除了导入和调用项目中其他地方定义的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包之外。这使得很难针对已安装的版本运行测试。
- 创建一个仅包含
__init__.py
的包,然后将所有代码放入__init__.py
。只需创建一个模块而不是一个包,它就更简单了。- 尝试提出神奇的黑客攻击,使Python能够导入您的模块或包,而无需用户将包含它的目录添加到其导入路径(通过PYTHONPATH或其他一些机制)。您将不正确处理所有情况,当您的软件无法在其环境中运行时,用户会对您生气。
答案 3 :(得分:104)
查看Open Sourcing a Python Project the Right Way。
让我摘录一下这篇优秀文章的项目布局部分:
设置项目时,布局(或目录结构)非常重要。合理的布局意味着潜在的贡献者不必花费永远寻找一段代码;文件位置很直观。由于我们正在处理现有项目,这意味着您可能需要移动一些东西。
让我们从顶部开始吧。大多数项目都有许多顶级文件(如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下的测试目录。
答案 4 :(得分:25)
" Python包装管理局"有一个示例项目:
https://github.com/pypa/sampleproject
这是一个示例项目,作为Python Packaging用户指南包装和分发项目教程的辅助。
答案 5 :(得分:16)
尝试使用python_boilerplate模板启动项目。它主要遵循最佳实践(例如those here),但如果您发现自己愿意在某个时刻将项目分成多个鸡蛋(并且相信我,除了最简单的项目之外的任何东西,那么一种常见的情况是你必须使用其他人的本地修改版本的库。)
您在哪里放置来源?
PROJECT_ROOT/src/<egg_name>
下的单独setuptools-layout。您在哪里放置应用启动脚本?
entry_point
。您在哪里放置IDE项目?
PROJECT_ROOT/.<something>
中,这很好。您在哪里进行单元/验收测试?
PROJECT_ROOT/src/<egg_name>/tests
目录中。我个人更喜欢使用py.test
来运行它们。您在哪里放置非Python数据,例如配置文件?
pkg_resources
包使用。PROJECT_ROOT/config
中。对于部署,可以有各种选项。在Windows上,可以在Linux上使用%APP_DATA%/<app-name>/config
,/etc/<app-name>
或/opt/<app-name>/config
。PROJECT_ROOT/var
中,并在Linux部署期间保留在/var
下。PROJECT_ROOT/src/<egg_name>/native
文档通常会进入PROJECT_ROOT/doc
或PROJECT_ROOT/src/<egg_name>/doc
(这取决于您是否将某些鸡蛋视为单独的大型项目)。其他一些配置将包含在PROJECT_ROOT/buildout.cfg
和PROJECT_ROOT/setup.cfg
等文件中。
答案 6 :(得分:14)
根据我的经验,这只是一个迭代问题。将您的数据和代码放在您认为的任何地方。机会是,你无论如何都会错。但是一旦你更好地了解事情将如何形成,你就可以更好地做出这些猜测了。
就扩展源而言,我们在trunk下有一个Code目录,其中包含python的目录和各种其他语言的目录。就个人而言,我更倾向于下次尝试将任何扩展代码放入自己的存储库中。
话虽如此,我回到最初的观点:不要做太大的交易。把它放在似乎适合你的地方。如果你发现一些不起作用的东西,可以(而且应该)改变它。
答案 7 :(得分:7)
非python数据最好使用setuptools中的package_data
支持捆绑在您的Python模块中。我强烈建议使用命名空间包来创建多个项目可以使用的共享命名空间 - 就像在com.yourcompany.yourproject
中放置包的Java约定(并且能够拥有共享的com.yourcompany.utils
命名空间)。
重新分支和合并,如果你使用足够好的源代码控制系统,即使通过重命名,它也会处理合并; Bazaar特别擅长这一点。
与此处的其他一些答案相反,我在+1 src
目录顶层(同时包含doc
和test
目录时)+1。文档目录树的具体约定将根据您使用的内容而有所不同;例如,Sphinx有自己的快速启动工具支持的约定。
请利用setuptools和pkg_resources;这使得其他项目更容易依赖于代码的特定版本(如果您使用package_data
,则可以使用不同的非代码文件同时安装多个版本。)