Python setup.py:如何包含本地包依赖?

时间:2018-04-13 13:48:33

标签: python setup.py

这个问题几乎是自我解释的。我有一个.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'

1 个答案:

答案 0 :(得分:0)

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

这里有两个不同的问题。首先是 zip 文件需要包含在您的发行版中。为此,请按照您的意图使用 package_data,但您需要为您的 包指定要在其中包含哪些数据。您可以按如下方式执行此操作:

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

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

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

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

./mypackage/vendor/dependencies/StreamingDataReader.zip

但要求用户这样做可能会带来不可接受的痛苦,而且对于依赖您的软件包的任何人来说都行不通。

(2) 蛮力。只需使用 zipfile 来展开包。

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

StreamingDataReader

等等。我还将假设您正在运行 Python 3.3 或更高版本,其中不再需要 StreamingDataReader/ StreamingDataReader/setup.py StreamingDataReader/StreamingDataReader/__init__.py 文件来创建包层次结构。 (在以前的版本中,您需要操作 __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依赖项,因为您没有使用 { 递归安装它{1}}。

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