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

时间:2008-10-10 21:50:34

标签: python directory-structure organization project-structure

想象一下,您希望在Python中开发一个非平凡的最终用户桌面(而非Web)应用程序。构建项目文件夹层次结构的最佳方法是什么?

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

特别是:

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

8 个答案:

答案 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/READMETwisted/setup.py来解释和安装您的软件。
  •   
     

不要:

     
      
  • 将您的来源放在名为srclib的目录中。这使得在没有安装的情况下很难运行。
  •   
  • 将您的测试放在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项目?

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

    • 每个鸡蛋都有一组单独的测试,保存在PROJECT_ROOT/src/<egg_name>/tests目录中。我个人更喜欢使用py.test来运行它们。
  • 您在哪里放置非Python数据,例如配置文件?

    • 这取决于。可以有不同类型的非Python数据。
      • &#34;资源&#34; ,即必须打包在鸡蛋中的数据。这些数据进入相应的egg目录,位于包命名空间内的某个位置。它可以通过pkg_resources包使用。
      • &#34; Config-files&#34; ,即非Python文件,它们被视为项目源文件的外部文件,但在应用程序启动时必须使用某些值进行初始化运行。在开发过程中,我更喜欢将这些文件保存在PROJECT_ROOT/config中。对于部署,可以有各种选项。在Windows上,可以在Linux上使用%APP_DATA%/<app-name>/config/etc/<app-name>/opt/<app-name>/config
      • 生成的文件,即应用程序在执行期间可能创建或修改的文件。我希望在开发过程中将它们保留在PROJECT_ROOT/var中,并在Linux部署期间保留在/var下。
  • 在哪里为pyd / so二进制扩展模块放置非Python源代码,如C ++?
    • 进入PROJECT_ROOT/src/<egg_name>/native

文档通常会进入PROJECT_ROOT/docPROJECT_ROOT/src/<egg_name>/doc(这取决于您是否将某些鸡蛋视为单独的大型项目)。其他一些配置将包含在PROJECT_ROOT/buildout.cfgPROJECT_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目录顶层(同时包含doctest目录时)+1。文档目录树的具体约定将根据您使用的内容而有所不同;例如,Sphinx有自己的快速启动工具支持的约定。

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