首页 文章

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

提问于
浏览
613

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

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

特别是:

  • 你在哪里放源?

  • 你在哪里放置应用程序启动脚本?

  • 你把IDE项目放在哪里?

  • 您在哪里进行单位/验收测试?

  • 你在哪里放置非Python数据,如配置文件?

  • 你在哪里为pyd / so二进制扩展模块放置非Python源代码如C?

8 回答

  • 320

    这个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或其他一些机制) . 您无法正确处理所有情况,当您的软件无法在其环境中工作时,用户会对您生气 .

  • 212

    看看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下的测试目录 .

  • 7

    “Python Packaging Authority”有一个示例项目:

    https://github.com/pypa/sampleproject

    它是一个示例项目,作为Python Packaging用户指南的包装和分发项目教程的辅助手段 .

  • 14

    没关系太重要了 . 无论什么让你快乐都会奏效 . 没有太多愚蠢的规则,因为Python项目可以很简单 .

    • /scripts/bin 用于那种命令行界面的东西

    • /tests 为您的测试

    • /lib 用于您的C语言库
      大多数文档都是

    • /doc
      019 /apidoc 用于Epydoc生成的API文档 .

    顶级目录可以包含README,Config和whatnot .

    很难选择是否使用 /src 树 . Python没有 /src/lib/bin 之间的区别,就像Java或C一样 .

    由于某些顶级 /src 目录被视为毫无意义,因此您的顶级目录可以是应用程序的顶级体系结构 .

    • /foo

    • /bar

    • /baz

    我建议将所有这些放在"name-of-my-product"目录下 . 因此,如果您正在编写名为 quux 的应用程序,则包含所有这些内容的目录名为 /quux .

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

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

  • 16

    根据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
    
  • 188

    尝试使用python_boilerplate模板启动项目 . 它主要遵循最佳实践(例如those here),但如果你发现自己愿意在某个时刻将你的项目分成多个鸡蛋(并且相信我,除了最简单的项目之外的其他任何东西,你都会这样 . )情况是您必须使用其他人的库的本地修改版本 .

    • Where do you put the source?

    • 对于体面的大型项目,将源分成几个蛋是有意义的 . 每个鸡蛋都会在 PROJECT_ROOT/src/<egg_name> 下作为单独的setuptools布局 .

    • Where do you put application startup scripts?

    • 理想的选择是将应用程序启动脚本在其中一个鸡蛋中注册为 entry_point .

    • Where do you put the IDE project cruft?

    • 取决于IDE . 他们中的许多人将他们的东西保存在项目的根目录中 PROJECT_ROOT/.<something> ,这很好 .

    • Where do you put the unit/acceptance tests?

    • 每个鸡蛋都有一组单独的测试,保存在 PROJECT_ROOT/src/<egg_name>/tests 目录中 . 我个人更喜欢使用 py.test 来运行它们 .

    • Where do you put non-Python data such as config files?

    • 这取决于 . 可以有不同类型的非Python数据 .

    • "Resources",即必须打包在鸡蛋中的数据 . 这些数据进入相应的egg目录,位于包命名空间内的某个位置 . 它可以通过 pkg_resources 包使用 .

    • "Config-files",即非Python文件,它们被视为项目源文件的外部文件,但在应用程序开始运行时必须使用某些值进行初始化 . 在开发过程中,我更喜欢将这些文件保存在 PROJECT_ROOT/config 中 . 对于部署,可以有多种选择 . 在Windows上,可以在Linux上使用 %APP_DATA%/<app-name>/config/etc/<app-name>/opt/<app-name>/config .

    • 生成的文件,即应用程序在执行期间可能创建或修改的文件 . 我希望在开发期间将它们保留在 PROJECT_ROOT/var 中,并在Linux部署期间保持在 /var 之下 .

    • Where do you put non-Python sources such as C++ for pyd/so binary extension modules?

    • 进入 PROJECT_ROOT/src/<egg_name>/native

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

  • 99

    根据我的经验,这只是一个迭代问题 . 将您的数据和代码放在您认为的任何地方 . 机会是,你无论如何都会错 . 但是一旦你更好地了解事情将如何形成,你就可以更好地做出这些猜测 .

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

    话虽如此,我回到最初的观点:不要做太大的交易 . 把它放在似乎适合你的地方 . 如果你发现一些不起作用的东西,它可以(而且应该)改变 .

  • 18

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

    重新分支和合并,如果你使用一个足够好的源控制系统,它将处理合并,即使通过重命名; Bazaar特别擅长这个 .

    与此处的其他一些答案相反,我只有一个 src 目录顶层(旁边有 doctest 目录) . 文档目录树的具体约定将根据您使用的内容而有所不同;例如,Sphinx有自己的快速入门工具支持的约定 .

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

相关问题