如何使用库作为源部署Python应用程序而没有进一步的依赖性?

时间:2009-02-09 09:20:17

标签: python deployment layout bootstrapping

背景:我有一个小型的Python应用程序,让开发人员在我们公司发布软件的生活变得更加轻松。我使用py2exe为Windows构建可执行文件。应用程序以及二进制文件都会检入Subversion。人们只需从SVN检出目录即可进行分发。该程序有大约6种不同的Python库依赖项(例如ElementTree,Mako)

情况:开发人员希望破解此工具的来源,然后在不必构建二进制文件的情况下运行它。目前这意味着他们需要一个python 2.6解释器(这很好),并且还使用easy_install在本地安装了6个库。

问题

  • 这不是一个公共的,经典的开源环境:我在公司网络中,该工具永远不会离开“围墙花园”,我们有很难到达外部互联网的障碍(NTLM验证代理和/或没有直接上网的机器。)
  • 我希望开始破解这个工具的障碍是最小的:没有人应该在正确的版本中寻找正确的依赖,他们应该尽可能少地执行。最好的先决条件是安装Python并从Subversion中检出程序。

轶事:流程越自包含就越容易重复。我让我的机器更换为新机器,并经历了不必要的过程,不得不对依赖项进行逆向工程,重新安装distutils,在线搜索库并让它们安装(参见上面的公司互联网限制)。

5 个答案:

答案 0 :(得分:9)

只需使用virtualenv - 它就是创建独立Python环境的工具。如果需要,您可以创建一个设置脚本并分发整个脚本。

答案 1 :(得分:8)

“我不喜欢这样一个事实,即开发人员(或者我开始使用干净的新机器)必须跳过必须在本地安装库才能开始使用的数据库”

为什么?

具体是什么 - 这是错误的?

你这样做是为了创建项目。您的项目非常受欢迎,其他人也希望这样做。

我没有看到问题。请根据您需要解决的具体问题更新您的问题。不喜欢分发开源的方式不是问题 - 这是开源工作的方式。

修改即可。 “围墙花园”并不重要。

选择1.你可以,BTW,建立一个“安装程序”,为他们运行easy_install 6次。

选择2.您可以保存easy_install将使用的所有安装程序工具包。然后,您可以提供一个解压缩的脚本和所有六个的python setup.py install

选择3.您可以提供site-packages的压缩版本。在安装Python之后,他们将您的site-packages目录解压缩到`C:\ Python2.5 \ lib \ site-packages``。

选择4.您可以为Python环境构建自己的MSI安装程序工具包。

选择5.您可以托管自己的类似pypi的服务器,并提供一个easy_install来检查您的服务器。

答案 2 :(得分:8)

我有时会使用下面描述的方法,因为@Boris声明的原因完全相同:我希望使用某些代码就像a)svn checkout / update - b)go。

但是为了记录:

  • 我大部分时间都使用virtualenv / easy_install。
  • 我在某种程度上同意@Ali A和@ S.Lott
  • 的批评

无论如何,我使用的方法取决于修改sys.path,并且工作方式如下:

  • 要在将使用您软件的所有计算机上安装python和setuptools(以启用从鸡蛋加载代码)。
  • 整理您的目录结构:
project/
    *.py
    scriptcustomize.py
    file.pth

    thirdparty/
        eggs/
            mako-vNNN.egg
            ... .egg
        code/
            elementtree\
                *.py
            ...
  • 在您的顶级脚本中,顶部包含以下代码:
from scriptcustomize import apply_pth_files
apply_pth_files(__file__)
  • 将scriptcustomize.py添加到项目文件夹:
import os
from glob import glob
import fileinput
import sys

def apply_pth_files(scriptfilename, at_beginning=False):
    """At the top of your script:
    from scriptcustomize import apply_pth_files
    apply_pth_files(__file__)

    """
    directory = os.path.dirname(scriptfilename)
    files = glob(os.path.join(directory, '*.pth'))
    if not files:
        return
    for line in fileinput.input(files):
        line = line.strip()
        if line and line[0] != '#':
            path = os.path.join(directory, line)
            if at_beginning:
                sys.path.insert(0, path)
            else:
                sys.path.append(path)
  • 将一个或多个* .pth文件添加到项目文件夹中。在每一行上,添加对包含目录的目录的引用。例如:
# contents of *.pth file
thirdparty/code
thirdparty/eggs/mako-vNNN.egg
  • 我喜欢这种方法。我喜欢什么:它类似于* .pth文件的工作方式,但是对于单个程序而不是整个站点包。我不喜欢的东西:必须在顶级脚本的开头添加两行。
  • 再次:我大部分时间都使用virtualenv。但我倾向于将virtualenv用于我可以严格控制部署方案的项目。在我没有严格控制的情况下,我倾向于使用上面描述的方法。这使得将项目打包为zip并让最终用户“安装”它(通过解压缩)非常容易。

答案 3 :(得分:0)

我同意Nosklo和S.Lott的回答。 (两者都是+1)

我可以补充一点,你想要做的事实上是一个可怕的想法

如果您真的希望人们破解您的代码,他们需要了解所涉及的库,它们如何工作,它们是什么,它们来自何处,每个文档等。确保为它们提供引导脚本但是除此之外,你将愚蠢地溺爱到他们无能为力的地步。

然后有一些特定的问题,例如“如果一个用户想要安装不同版本或库的实现怎么办?”,这里有一个明显的例子是ElementTree,因为它有许多实现。

答案 4 :(得分:0)

我并不是说这是一个好主意,但通常我在这样的情况下做的是我有一个Makefile,检查到subversion,其中包含make规则来获取所有依赖库并安装它们。 makefile可以足够智能,只有在它们不存在时才应用依赖库,所以这可能相对较快。

项目的新开发人员只需从subversion中检出,然后键入“make”。

这种方法可能适合您,因为您的受众已经习惯了将subversion结帐作为其获取过程的一部分。此外,它具有很好的属性,所有关于您的程序的知识,包括其外部依赖性,都在源代码存储库中捕获。