【问题标题】:Python setup.py: how to include local package dependency?Python setup.py:如何包含本地包依赖项?
【发布时间】:2018-04-13 13:48:32
【问题描述】:

这个问题几乎是不言自明的。我有一个 .zip 包依赖项,我需要将其包含在我的 python 包安装中。那么如何在我的setup.py 中包含这个本地依赖项?我有 install_requires 但这会从 PyPI 加载我的依赖包,这在这种情况下不是我想要的。

我项目中最相关的文件结构如下:

myproject
|- setup.py
|- mypackage
   |- __init__.py
   |- vendor
      |- __init__.py
      |- dependencies
         |- StreamingDataReader.zip

然后我尝试了...

include_package_data=True,
package_data={
    'StreamingDataReader': ['mypackage/vendor/dependencies/StreamingDataReader.zip'],
}

...没有成功。我的代码仍然找不到包:ImportError: No module named 'StreamingDataReader'

【问题讨论】:

  • 有几种方法可以包含数据文件。您是否阅读过setuptools 文档中的Including Data Files 部分?
  • 我遇到过这个package_data,但我没有找到任何完整的例子
  • 能否分享一下你项目的目录结构,包括相关文件在哪里?
  • package_data 映射构造为{'Name of Pacakge': ['list', 'of', 'patterns']}。试试类似{'': ['*.zip']} 的东西。这应该包括项目中的每个 .zip 文件。
  • 谢谢。但是['mypackage/vendor/dependencies/StreamingDataReader.zip']仍然是一种模式

标签: python setup.py


【解决方案1】:

这是一个老问题,但我有话要说,所以我发帖。

这里有两个不同的问题。首先是 zip 文件需要包含在您的发行版中。为此,请按您的意图使用package_data,但您需要为您的 包指定要包含的数据。你可以这样做:

   package_data= {"mypackage": ["vendor/dependencies/StreamingDataReader.zip"]}

不要不要同时使用include_package_data;这会在 MANIFEST.in 中查找数据并忽略 package_data 参数。 setuptools 的设计真的很糟糕。对于二进制和源代码打包,我发现的最佳建议是确保所有数据都在包目录中,并使用 package_data 而不是其他任何东西。

您的第二个问题是您希望能够导入StreamingDataReader。不幸的是,据我所知,没有办法用pip 使用pip install 来做到这一点,仅此而已。您有两个明显的选择:

(1) 您可以包含一个requirements.txt 文件并将压缩文件列为要求,并让人们在pip install您的项目之前执行pip install -r requirements.txt。您的 requirements.txt 文件如下所示:

./mypackage/vendor/dependencies/StreamingDataReader.zip

但是要求用户这样做可能是一种无法接受的痛苦程度,并且对于任何依赖你的包的人都不起作用。

(2) 蛮力。只需使用zipfile 扩展包即可。

我将假设 StreamingDataReader.zip 文件是一个 Python 包 zip,在顶层有一个目录(我假设它称为 StreamingDataReader),其中包含一个顶层 setup.py 和一个子目录,让我们假设它被称为StreamingDataReader,其中包含实际的软件。换句话说,我假设你的 zip 看起来像这样:

StreamingDataReader/
StreamingDataReader/setup.py
StreamingDataReader/StreamingDataReader/__init__.py

等等。我还将假设您正在运行 Python 3.3 或更高版本,其中不再需要 __init__.py 文件来创建包层次结构。 (在以前的版本中,您需要操作sys.path,这没什么大不了的,但现在更容易了。)所以vendor/__init__.py 没有为您做任何工作。

顺便说一下,这个解决方案假定运行你的软件的人将拥有包含它的目录的写权限。

将以下内容放入您的顶层__init__.py

import zipfile, pathlib

_mpath = pathlib.Path(__file__).resolve().parent
_sdrDir = mpath.joinpath("vendor", "dependencies", "StreamingDataReader")
if not _sdrDir.is_dir():
    _z = zipfile.Zipfile(sdrDir.parent.joinpath("StreamingDataReader.zip"), "r")
    _z.extractall(sdrDir.parent)
    _z.close()
    del _z
# cleanup
del _mpath
del _sdrDir

一旦你这样做了,你就可以

import mypackage.vendor.dependencies.StreamingDataReader.StreamingDataReader as StreamingDataReader

随心所欲。

然后,最后,在您的软件包的 setup.py 中,您需要包含 StreamingDataReader依赖项,因为您没有使用 pip 递归安装它。

是的,这是很多工作。但据我所知,Python 安装机制中没有其他工具可以从您自己提供的 zip 文件中安装包。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-10
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 2014-04-04
    • 1970-01-01
    • 2016-03-24
    相关资源
    最近更新 更多