Python应用程序的最佳项目结构是什么?

想象一下,你想在Python中开发一个不重要的terminal用户桌面(而不是web)应用程序。 什么是最好的方式来构build项目的文件夹层次结构?

理想的function是易于维护,IDE友好,适用于源代码控制分支/合并以及易于生成安装包。

尤其是:

  1. 你把源头放在哪里?
  2. 你在哪里放置应用程序启动脚本?
  3. 你把IDE项目放在哪里?
  4. 你在哪里进行单元/验收testing?
  5. 你在哪里放置非Python数据,如configuration文件?
  6. 你在哪里放置非Python源码,如C ++ for pyd / so二进制扩展模块?

不要太重要。 无论什么让你快乐将工作。 没有太多愚蠢的规则,因为Python项目可能很简单。

  • /scripts/bin这种命令行界面的东西
  • /tests你的testing
  • /lib为您的C语言库
  • /doc大多数文档
  • /apidoc为Epydoc生成的API文档。

顶层目录可以包含自述文件,configuration文件和其他文件。

硬select是否使用/src树。 Python没有像Java或C所具有的/src/lib/bin之间的区别。

由于顶层/src目录被某些人认为是没有意义的,所以你的顶层目录可以是你的应用程序的顶层体系结构。

  • /foo
  • /bar
  • /baz

我build议将所有这些放在“我的产品名称”目录下。 所以,如果你正在编写一个名为quux的应用程序,那么包含所有这些东西的目录就是/quux

然后,另一个项目的PYTHONPATH可以包含/path/to/quux/foo来重用QUUX.foo模块。

在我的情况下,因为我使用Komodo编辑,我的IDE cuft是一个.KPF文件。 我实际上把它放在顶层/quux目录中,并且省略了将其添加到SVN。

根据Jean-Paul Calderone的Python项目的文件系统结构 :

 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
  • 创build一个目录Twisted/bin并把你的可执行文件放在那里,如果你有的话。 不要给他们一个.py扩展名,即使他们是Python源文件。 除了导入和调用项目中其他位置定义的主函数之外,不要在其中放置任何代码。 (轻微的皱纹:因为在Windows上,解释器是通过文件扩展名来select的,所以你的Windows用户确实需要.py扩展名。所以,当你为Windows打包的时候,你可能需要添加这个扩展名。我知道这个过程是自动化的,考虑到在POSIX上.py扩展名是唯一的一个疣,而在Windows上缺乏是一个实际的错误,如果你的用户库包括Windows用户,你可能想select只是.py到处扩展。)
  • 如果你的项目可以作为单一的Python源文件expression,那么把它放到目录中,并命名为与你的项目相关的东西。 例如, Twisted/twisted.py 。 如果您需要多个源文件,请创build一个包( Twisted/twisted/ ,带有一个空的Twisted/twisted/__init__.py ),然后放置源文件。 例如, Twisted/twisted/internet.py
  • 把你的unit testing放在你的包的子包中(注意 – 这意味着上面的单个Python源文件选项是一个窍门 – 你总是至less需要另外一个文件来进行unit testing)。 例如, Twisted/twisted/test/ 。 当然,使它成为Twisted/twisted/test/__init__.py 。 将testing放在Twisted/twisted/test/test_internet.py
  • 如果你感觉不错,分别添加Twisted/READMETwisted/setup.py来解释和安装你的软件。

别:

  • 把你的源码放在一个名为srclib的目录中。 这使得无需安装就很难运行。
  • 把你的testing放在你的Python包之外。 这使得难以针对已安装的版本运行testing。
  • 创build一个包含__init__.py的包,然后将所有代码放入__init__.py 。 只需制作一个模块而不是一个软件包,这很简单。
  • 尝试拿出神奇的黑客,使Python能够导入您的模块或包,而无需用户将包含它的目录添加到他们的导入path(通过PYTHONPATH或其他机制)。 你不能正确处理所有情况,当你的软件不能在其环境中工作时,用户会对你生气。

查看以正确的方式开源Python项目 。

让我摘录这篇文章的项目布局部分:

设置项目时,布局(或目录结构)对于正确设置非常重要。 一个合理的布局意味着潜在的贡献者不必花费永远狩猎一段代码; 文件位置很直观。 由于我们正在处理现有的项目,这意味着您可能需要移动一些东西。

我们从顶部开始。 大多数项目都有一些顶级文件(如setup.py,README.md,requirements.txt等)。 那么每个项目应该有三个目录:

  • 包含项目文档的文档目录
  • 一个以项目名称命名的目录,用于存储实际的Python包
  • 在两个地方之一的testing目录
    • 在包含testing代码和资源的软件包目录下
    • 作为一个独立的顶级目录为了更好地理解您的文件应该如何组织,下面是我的一个项目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下的testing目录。

Python的文档也很值得一读。

http://docs.python.org/tutorial/modules.html#packages

另外请确保您熟悉该页面上的其他信息。

尝试使用python_boilerplate模板启动项目。 它基本上遵循最佳实践(例如这里的那些实践),但是如果您发现自己愿意在某个时候将您的项目分成多个蛋,并且相信我,除了最简单的项目之外,常见的情况是你必须使用其他人的库的本地修​​改版本)。

  • 你把源头放在哪里?

    • 对于体面大的项目来说,把源代码分成几个蛋是有意义的。 每个蛋都将作为一个独立的setuptools布局在PROJECT_ROOT/src/<egg_name>
  • 你在哪里放置应用程序启动脚本?

    • 理想的select是将应用程序启动脚本注册为其中一个entry_point
  • 你把IDE项目放在哪里?

    • 取决于IDE。 他们中的许多人把他们的东西保存在PROJECT_ROOT/.<something>项目的根目录下,这很好。
  • 你在哪里进行单元/验收testing?

    • 每个蛋都有一套独立的testing,保存在PROJECT_ROOT/src/<egg_name>/tests目录中。 我个人更喜欢使用py.test来运行它们。
  • 你在哪里放置非Python数据,如configuration文件?

    • 这取决于。 可以有不同types的非Python数据。
      • “资源” ,即必须包装在蛋中的数据。 这些数据进入相应的egg目录,在package命名空间的某个地方。 它可以通过pkg_resources包来使用。
      • “configuration文件” ,即被视为项目源文件外部的非Python文件,但在应用程序开始运行时必须使用某些值进行初始化。 在开发过程中,我更喜欢将这些文件保存在PROJECT_ROOT/config 。 部署可以有多种select。 在Windows上,可以在Linux, /etc/<app-name>/opt/<app-name>/config使用%APP_DATA%/<app-name>/config /opt/<app-name>/config
      • 生成的文件 ,即应用程序在执行过程中可能创build或修改的文件。 我希望在开发期间将它们保存在PROJECT_ROOT/var中,在Linux部署期间保留在PROJECT_ROOT/var下。
  • 你在哪里放置非Python源码,例如C ++ for pyd / so二进制扩展模块?
    • 进入PROJECT_ROOT/src/<egg_name>/native

文档通常会进入PROJECT_ROOT/docPROJECT_ROOT/src/<egg_name>/doc (这取决于您是否将某些鸡蛋视为单独的大型项目)。 一些额外的configuration将在PROJECT_ROOT/buildout.cfgPROJECT_ROOT/setup.cfg

根据我的经验,这只是一个迭代的问题。 把你的数据和代码放在任何你认为他们去的地方。 有机会,反正你会错的。 但是一旦你更清楚地知道事情将如何形成,你就可以更好地进行这种猜测了。

至于扩展源,我们有一个在trunk下的Code目录,它包含一个python目录和一个其他各种语言的目录。 就个人而言,我更倾向于尝试将下一次扩展代码放入自己的存储库中。

就这样说,我回到了我的初衷:不要做太多的事情。 把它放在一个似乎适合你的地方。 如果发现一些不起作用的东西,可以(也应该)改变。

非python数据最好使用setuptools中的package_data支持捆绑在Python模块中。 我强烈build议的一件事是使用命名空间包来创build多个项目可以使用的共享命名空间,就像将包放入com.yourcompany.yourproject (并能够具有共享com.yourcompany.utils命名空间)的Java约定一样。

重新分支和合并,如果你使用了足够好的源代码控制系统,它将处理合并,甚至通过重命名; 集市尤其擅长这一点。

与其他答案相反,我在+1上有一个src目录顶层( doctest目录旁边)。 文档目录树的具体约定取决于你正在使用的内容。 例如, 狮身人面像有它自己的快速启动工具支持的约定。

请使用setuptools和pkg_resources; 这使得其他项目更容易依赖于特定版本的代码(并且如果使用package_data ,多个版本可以同时安装不同的非代码文件)。

“Python包装pipe理局”有一个样品项目:

https://github.com/pypa/sampleproject

这是一个样本项目,作为对Python打包用户指南打包和分发项目教程的帮助。