Python 代码组织问题:Eggs + Packages + Buildout + 单元测试 + SVN

8
我有几个Python项目共享通用模块。到目前为止,我一直在...咳咳...手动保留多个共同的代码副本并进行同步。但是,我显然更喜欢做其他事情。
现在看来,zc.Buildout可能是我需要的东西。我想我应该将系统中每个可重用的组件放入单独的egg中,然后使用buildout将它们组装成项目。
我还在考虑,对于任何特定模块,我应该将单元测试放入单独的包或egg中,这样我就不必在每个项目中安装组件的单元测试副本。我只想在开发库的地方进行单元测试,而不是在仅使用库的地方。
所以也许我需要像这样的东西。
projects
  lib1
    tests
    code
  lib2
    tests
    code
  app1
    tests 
    appcode
  app2
    tests
    appcode

在这种情况下,app1和app2是独立的应用程序,拥有自己的代码和测试,但也包含并使用lib1和lib2。而lib1/test、lib1/code、lib2/test、lib2/code、app1和app2是单独的egg文件。这听起来对吗?

然而,我现在感到困惑。我认为当我开发app1时,我希望buildout将lib1、lib2和app1的副本拉入一个单独的工作目录,而不是直接将这些库的副本放在app1下。但是这如何与我的SVN源代码控制一起工作呢?如果工作目录是动态构建的buildout,它不能是一个实时的SVN目录,我无法将更改检查回存储库中。

我是否误解了buildout的使用方式?我是否应该采取完全不同的方法?如何在项目之间混合使用源代码控制和模块重用?

更新:感谢两位回答了这个问题的人。我正在进行更多的实验。


为什么$PYTHONPATH不够用? - jfs
我的意思是:您只需保留每个项目的单个实例,并修改$PYTHONPATH以从其他项目中查找所需的模块。 - jfs
4个回答

5
不要将测试与代码分开,需要将两者紧密结合。毕竟测试并不占用太多磁盘空间或内存!同时,测试对于您的库用户来说也非常有指导意义。
对于库包,包含一个 buildout.cfgbootstrap.py 文件可以方便地运行测试。例如,参见 plone.reload package;请注意它如何使用 zc.recipe.testrunner 部件创建一个测试脚本,自动发现并运行测试。这样,您可以确保您的库包始终通过了测试!
然后,您的应用程序包只需要测试集成和特定于应用程序的代码。同样,将测试与包一起包含,以避免在编写代码时忘记测试。在您的 buildout 中使用 zc.recipe.testrunner 部件来发现和运行这些测试。
最后,使用mr.developer来管理您的包。使用mr.developer,您可以在开发过程中检查软件包,或者如果您不需要处理代码,则依赖于发布的版本。一个较大的项目将具有许多依赖项,其中许多不需要您调整代码。使用mr.developer,您可以随意提取源代码并将其转换为开发蛋,直到您发布该代码并可以再次取消签出。
要查看这种项目buildout的实际示例,请参阅Plone核心开发buildoutsources.cfg文件包含各种软件包的SCM位置的长列表,但通常使用发布版本的egg,直到您明确激活要处理的软件包。 checkouts.cfg列出默认情况下检出的所有软件包;这些软件包具有将成为Plone下一个版本的一部分并尚未发布的更改。 如果您在使用Plone,则需要它们,因为您不能忽略这些更改。 testing.cfg列出了您需要测试的所有软件包,如果您想要测试Plone,则是一个很大的列表。
请注意,Plone的源代码来自各种位置。 一旦您开始使用buildout和mr.developer管理软件包,您可以从任何地方获取源代码。

2
这就是为什么有 site 模块。它将内部的 sys.path 设置为包括以下所有包和模块:
  • lib/site-packages -- 包括目录、eggs 和 .pth 文件。
  • PYTHONPATH
这样,你的库就只有一个工作副本。
有无限种方法可以使用它。以下是其中两种:
  1. 在每个 lib 中编写一个 setup.py,以正确部署你的 lib。当你做出更改时,进行 svn up 收集更改,并进行 python setup.py install 部署每个应用程序共享的一个工作副本。

  2. 在每个 app 中,依赖于 PYTHONPATH 环境变量中的内容。确保 projects/lib1projects/lib2PYTHONPATH 中。然后每个应用程序都共享各种库的一个工作副本。


2
我已经在 SVN 中有效地使用了以下结构。
Lib1/
   branches/
   tags/
   trunk/
     lib1/
     tests/
     setup.py
Lib2
   branches/
   tags/
   trunk/
     lib2/
     tests/
     setup.py
App1
   branches/
   tags/
   trunk/
     app1/
     tests/
     setup.py
App2
   branches/
   tags/
   trunk/
     app2/
     tests/
     setup.py

我会按照以下步骤创建我的开发工作空间(我使用eclipse/pydev),从主干或分支中签出。

Lib1/
   lib1/
   tests/
   setup.py
Lib2/
   lib2/
   tests/
   setup.py
App1/
   app1/
   tests/
   setup.py
App2/
   app2/
   tests/
   setup.py

我会使用eclipse项目依赖设置python路径,这可以很好地与eclipse代码自动完成功能配合使用。setup.py也可以使用,但不支持多个工作区。

对于部署,我会创建一个包含以下结构的单个zip文件。

App1/
   lib1-1.1.0-py2.5.egg/
   lib2-1.1.0-py2.5.egg/
   app1/
   sitecustomize.py

App2/
   lib1-1.2.0-py2.5.egg/
   lib2-1.2.0-py2.5.egg/
   app2/
   sitecustomize.py

我不使用安装程序,因为我希望支持多个应用程序版本,并且我可以控制运行时环境。因此,在我的部署中,我不会打包Python,但如果需要的话,将Python添加到部署包中应该很容易。


1

我会把每个应用程序和库都视为一个“蛋”,并使用已经给出的示例来在SVN中进行布局。实际上,版本控制系统方面不应该成为问题。

然后,为了测试每个应用程序/库或组合,我会设置一个虚拟环境,并通过setup.py develop或实际安装来安装每个软件包。Virtualenvwrapper也是一个有用的工具,可以管理这些环境,您可以简单地执行以下操作:

mkvirtualenv lib1-dev

然后稍后:

workon lib1-dev

Virtualenv使用PYTHONPATH来更精细地控制安装的软件包。同样,您可以使用以下命令创建环境:

virtualenv --no-site-packages some-env

它将省略任何对您实际系统网站包的引用。这很有帮助,因为您不仅可以测试您的库/应用程序,而且还可以在安装时验证您是否具有正确的依赖项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接