【问题标题】:What's the standard way to package a python project with dependencies?使用依赖项打包 python 项目的标准方法是什么?
【发布时间】:2016-11-09 15:59:46
【问题描述】:

我有一个 python 项目,它有一些依赖项(在 setup.py 中的 install_requires 下定义)。我的操作人员需要一个独立的包,并且只依赖于 python 安装。试金石是他们能够获得一个 zip 文件,然后在没有互联网连接的情况下解压缩并运行它。

有没有一种简单的方法来打包包含依赖项的安装?如果我必须在最终运行它的操作系统/架构上构建,这是可以接受的。

对于它的价值,我尝试了setup.py buildsetup.py sdist,但它们似乎不符合要求,因为它们不包含依赖项。我也考虑过virtualenv(如果绝对必要,可以安装),但它有硬编码的路径,这使得它不太理想。

【问题讨论】:

  • 不要认为有标准的方法可以做到这一点。
  • 为什么不使用 requirements.txt 和依赖关系?还是不能运行pip install -r requirements.txt
  • 我认为您必须创建一个捆绑的可执行文件,其中有各种工具。顺便说一句,如果你有“devops 人”,并且不能只部署自己,那不是 devops
  • docker中的依赖项打包你的项目
  • @jonrsharpe 关于 devops 的好点子!更改为操作 :)

标签: python setuptools


【解决方案1】:

pip 的工作方式有一些细微差别。不幸的是,如果这些依赖项中的任何一个或依赖项的依赖项安装到 pip 可以找到它们的位置,则使用 --prefix vendor 存储项目的所有依赖项将不起作用。它将跳过这些依赖项,并将其余的安装到您的 vendor 文件夹中。

过去我使用 virtualenv 的 --no-site-packages 选项来解决这个问题。在一家公司,我们会发布整个 virtualenv,其中包括 python 二进制文件。为了只提供依赖项,您可以将 virtualenv 与 pip 上的 --prefix 开关结合使用,为自己提供一个安装到正确位置的干净环境。

我将提供一个示例脚本,它创建一个临时 virtualenv,激活它,然后将依赖项安装到本地 vendor 文件夹。如果您在 CI 中运行,这将非常方便。

#!/bin/bash

tempdir=$(mktemp -d -t project.XXX) # create a temporary directory
trap "rm -rf $tempdir" EXIT         # ensure it is cleaned up
# create the virtualenv and exclude packages outside of it
virtualenv --python=$(which python2.7) --no-site-packages $tempdir/venv
# activate the virtualenv
source $tempdir/venv/bin/activate    
# install the dependencies as above
pip install -r requirements.txt --prefix=vendor

【讨论】:

    【解决方案2】:

    使用最新版本的pip 可以做到这一点(我使用的是 8.1.2)。在构建机器上:

    pip install -r requirements.txt --prefix vendor
    

    然后运行它:

    PYTHONPATH=vendor/lib/python2.7/site-packages python yourapp.py
    

    (这基本上是@valentjedi 评论的扩展。谢谢!)

    【讨论】:

    • 这个--prefix vendor似乎与添加供应商名称无关,这只是指定了安装包的文件夹。
    • 正确,它只是放置供应商依赖项的文件夹的名称。
    【解决方案3】:

    在大多数情况下,您应该能够“供应”所有依赖项。它基本上是一个粗略的 virtualenv 版本。

    例如,看看requests 如何将includes chardet and urllib3 封装在它自己的源代码树中。这是一个示例脚本,应该为您完成初始下载和复制:https://gist.github.com/proppy/1136723

    安装依赖项后,您可以使用from .some.namespace import dependency_name 引用它们,以确保您使用的是本地版本。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-18
    • 2019-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    • 2021-08-07
    • 1970-01-01
    相关资源
    最近更新 更多