Python:为什么pip install不从sdist部署我的代码?



我正在尝试将一个小型Python 3.9应用程序打包在.tar.gz软件发行文件(又名"sdist")中。

我的代码有这样的结构:

my-code
PackageA
PackageB
Module1.py
__init__.py 
__init__.py
setup.py

我的setup.py文件看起来像这样:

from setuptools import find_packages, setup
setup(
name="my-code",
version="0.1",
install_requires=[],
packages=find_packages(include=["PackageA.PackageB"]),
include_package_data=True,
description="My Code"
)

当我运行python setup.py sdist --formats=gztar时,我成功地获得了my-code-0.1.tar.gz文件,我可以看到它包含我的.py文件。

然而,当我运行pip install my-code-0.1.tar.gz时,似乎pip不编译和部署我的.py文件。即,当我安装到venv并查看venvLib/site-packages目录时,我只看到一个名为my_code-0.1-py3.9.egg-info的目录,而我的代码不在其中。试图导入或运行PackageA.PackageB中的模块失败。

我的问题是-为什么我的代码不是由pip install构建和安装的,我怎么能解决这个问题?

TL;DR,因为find_packages(include=["PackageA.PackageB"])会过滤掉父PackageA,所以不包含在安装中。只使用

setup(
packages=find_packages(),
...
)

天会好的。

更详细的解释是,include参数并不意味着"除了find_packages()发现的内容之外还包括"。它的意思是"只包括find_packages()找到的在include过滤器列表中的包",所以它只能缩小包的选择。比较

的输出
$ python -c "from setuptools import find_packages as f; print(f())"
['PackageA', 'PackageA.PackageB']

$ python -c "from setuptools import find_packages as f; print(f(include=['PackageA.PackageB']))"
['PackageA.PackageB']

由于PackageA不包括在内,PackageA/__init__.py将在源代码发行版中被省略,有效地从tar存档中的PackageA中删除包属性,现在它将是一个常规目录。运行pip install mydist.tar.gz将找不到PackageA,因此PackageA.PackageB也找不到。因此,不会安装任何东西。setuptools文档中的自动包发现部分简短地提到了find_packages()includeexclude参数,但在我看来,更有用的是函数的docstring:

>>> from setuptools import find_packages
>>> help(find_packages)
find(where='.', exclude=(), include=('*',)) method of builtins.type instance
Return a list all Python packages found within directory 'where'
...
'include' is a sequence of package names to include.  If it's
specified, only the named packages will be included.  If it's not
specified, all found packages will be included.  'include' can contain
shell style wildcard patterns just like 'exclude'.