问题:Python应用程序的最佳项目结构是什么?[关闭]
想象一下,您想使用Python开发非平凡的最终用户桌面(非Web)应用程序。构造项目文件夹层次结构的最佳方法是什么?
理想的功能是易于维护,IDE友好,适用于源代码控制分支/合并以及易于生成安装软件包。
特别是:
- 您将源放在哪里?
- 您将应用程序启动脚本放在哪里?
- 您将IDE项目放在哪里?
- 您将单元/验收测试放在哪里?
- 您将非Python数据(例如配置文件)放在哪里?
- 您在哪里将非Python来源(例如C ++)用于pyd / so二进制扩展模块?
回答 0
没什么大不了的。令您快乐的一切都会起作用。没有很多愚蠢的规则,因为Python项目可以很简单。
/scripts
或/bin
那种命令行界面的东西/tests
为您的测试/lib
用于您的C语言库/doc
对于大多数文档/apidoc
用于Epydoc生成的API文档。
顶级目录可以包含自述文件,配置文件和其他内容。
困难的选择是是否使用/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
根据Jean-Paul Calderone的Python项目的文件系统结构:
Project/
|-- bin/
| |-- project
|
|-- project/
| |-- test/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- setup.py
|-- README
回答 2
此博客由让-保罗·Calderone的岗位如Freenode上的#python答案通常是给出。
Python项目的文件系统结构
做:
- 为目录命名与您的项目相关的名称。例如,如果您的项目名为“ Twisted”,请为其源文件命名顶级目录
Twisted
。发行时,应包括版本号后缀:Twisted-2.5
。- 创建目录
Twisted/bin
,然后将可执行文件放在此处(如果有)。.py
即使它们是Python源文件,也不要给它们扩展名。除了在项目中其他地方定义的main函数的导入和调用外,不要在其中添加任何代码。(略有起皱:由于在Windows上,解释器是由文件扩展名选择的,因此Windows用户实际上确实希望使用.py扩展名。因此,在为Windows打包时,可能需要添加它。不幸的是,没有简单的distutils技巧可以考虑到在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
以正确的方式查看Open Sourcing 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下的test目录。
回答 4
“ Python包装管理中心”有一个示例项目:
https://github.com/pypa/sampleproject
它是一个示例项目,可作为《 Python打包用户指南》中有关打包和分发项目的教程的辅助工具而存在。
回答 5
尝试使用python_boilerplate模板启动项目。它在很大程度上遵循了最佳实践(例如此处的),但是如果您发现自己愿意在某个时候将您的项目分成多个鸡蛋(并且相信我,除了最简单的项目之外的其他项目,您会做到),它会更适合。常见的情况是您必须使用其他人的库的本地修改版本)。
您将源放在哪里?
- 对于大型项目,将源分成几个鸡蛋是有意义的。每个鸡蛋将在下作为单独的setuptools-layout放置
PROJECT_ROOT/src/<egg_name>
。
- 对于大型项目,将源分成几个鸡蛋是有意义的。每个鸡蛋将在下作为单独的setuptools-layout放置
您将应用程序启动脚本放在哪里?
- 理想的选择是将应用程序启动脚本注册为
entry_point
其中一个鸡蛋。
- 理想的选择是将应用程序启动脚本注册为
您将IDE项目放在哪里?
- 取决于IDE。他们中的许多人将自己的东西保存
PROJECT_ROOT/.<something>
在项目的根目录中,这很好。
- 取决于IDE。他们中的许多人将自己的东西保存
您将单元/验收测试放在哪里?
- 每个鸡蛋都有单独的一组测试,并保存在其
PROJECT_ROOT/src/<egg_name>/tests
目录中。我个人更喜欢使用py.test
它们来运行它们。
- 每个鸡蛋都有单独的一组测试,并保存在其
您将非Python数据(例如配置文件)放在哪里?
- 这取决于。可能有不同类型的非Python数据。
- “资源”,即必须包装在一个鸡蛋中的数据。该数据进入包命名空间中某个位置的相应egg目录。可以通过
pkg_resources
从中的包使用它,也可以从标准库中setuptools
的importlib.resources
模块通过Python 3.7开始使用。 - “配置文件”,即非Python文件,它们被视为项目源文件的外部文件,但在应用程序开始运行时必须使用一些值进行初始化。在开发过程中,我更喜欢将此类文件保存在中
PROJECT_ROOT/config
。对于部署,可以有多种选择。在Windows%APP_DATA%/<app-name>/config
上,可以在Linux/etc/<app-name>
或上使用/opt/<app-name>/config
。 - 生成的文件,即应用程序在执行期间可以创建或修改的文件。我希望
PROJECT_ROOT/var
在开发/var
期间以及在Linux部署期间保留它们。
- “资源”,即必须包装在一个鸡蛋中的数据。该数据进入包命名空间中某个位置的相应egg目录。可以通过
- 这取决于。可能有不同类型的非Python数据。
- 您在哪里将非Python来源(例如C ++)用于pyd / so二进制扩展模块?
- 进入
PROJECT_ROOT/src/<egg_name>/native
- 进入
文件通常会放入PROJECT_ROOT/doc
或PROJECT_ROOT/src/<egg_name>/doc
(取决于您是否将某些鸡蛋视为一个单独的大型项目)。一些其他配置将在PROJECT_ROOT/buildout.cfg
和文件中PROJECT_ROOT/setup.cfg
。
回答 6
以我的经验,这只是迭代问题。将您的数据和代码放在您认为任何地方。很有可能,无论如何你都会错的。但是,一旦您对事物的确切形状有了一个更好的了解,您就可以进行这些猜测。
至于扩展源,我们在主干下有一个Code目录,其中包含python目录和各种其他语言的目录。就个人而言,下一次我更倾向于尝试将任何扩展代码放入其自己的存储库中。
话虽如此,我回到了我的初始观点:不要做太大的事情。将其放在似乎对您有用的位置。如果发现不起作用,则可以(并且应该)对其进行更改。
回答 7
最好使用setuptools中的package_data
支持将非Python数据捆绑到您的Python模块中。我强烈建议您使用命名空间包来创建多个项目可以使用的共享命名空间,这很像Java约定(将软件包放入其中并能够拥有一个共享命名空间)。com.yourcompany.yourproject
com.yourcompany.utils
重新分支和合并,如果您使用足够好的源代码控制系统,它将通过重命名来处理合并;集市在这方面尤其擅长。
与这里的其他答案相反,我对拥有src
顶级目录(带有doc
和test
目录并在旁边)+1 。文档目录树的特定约定将根据您所使用的内容而有所不同。例如,Sphinx有其快速启动工具支持的自己的约定。
请,请利用setuptools和pkg_resources;这使其他项目更容易依赖于代码的特定版本(如果使用,则多个版本可以与不同的非代码文件同时安装package_data
)。