Python setup.py:如何获取 find_packages() 以识别子目录中的包

Joe*_*e J 17 python distutils pip setuptools setup.py

我正在尝试创建一个 setup.py 文件,其中 find_packages() 递归地查找包。在这个例子中,foo, bar, 和baz都是我想要安装并在 python 路径上可用的模块。例如,我希望能够做到import foo, bar, baz. 该bar-packfoo-pack只是常规的非蟒目录将包含各种支持文件/显示目录(如测试,自述等,具体到相应的模块)。

??? bar-pack
?   ??? bar
?       ??? __init__.py
??? baz
?   ??? __init__.py
??? foo-pack
?   ??? foo
?       ??? __init__.py
??? setup.py

Run Code Online (Sandbox Code Playgroud)

然后说setup.py如下:

from setuptools import setup, find_packages
setup(
    name="mypackage",
    version="0.1",
    packages=find_packages(),
)

Run Code Online (Sandbox Code Playgroud)

但是,当我运行python setup.py installor 时python setup.py sdist,只有baz目录被识别和打包。

我可以进一步简化它,并运行以下命令,但同样,只有baz被识别。

python -c "from setuptools import setup, find_packages; print(find_packages())"
['baz']
Run Code Online (Sandbox Code Playgroud)

您知道我如何扩展 find_packages() 的搜索路径(或手动硬编码搜索路径)吗?

任何帮助表示赞赏。

wim*_*wim 19

这就像对 "foo" 和 "bar" 包使用src-layout,但对 "baz" 布局使用平面布局。这是可能的,但需要在setup.py.

Setuptoolsfind_packages支持“where”关键字(docs),您可以使用它。

setup(
    ...
    packages=(
        find_packages() +
        find_packages(where="./bar-pack") +
        find_packages(where="./foo-pack")
    ),
    ...
)
Run Code Online (Sandbox Code Playgroud)

由于find_packages返回一个普通的旧列表,您也可以手动列出您的包,这可以说更容易/不那么神奇。

setup(
    ...
    packages=["baz", "bar", "foo"],
    ...
)
Run Code Online (Sandbox Code Playgroud)

非标准的目录结构意味着您还需要package_dir为 distutils指定结构,它描述了放置已安装包的位置。

拼凑起来:

setup(
    name="mypackage",
    version="0.1",
    packages=["baz", "bar", "foo"],
    package_dir={
        "": ".",
        "bar": "./bar-pack/bar",
        "foo": "./foo-pack/foo",
    },
)
Run Code Online (Sandbox Code Playgroud)

上面的安装程序将在站点包中创建此目录结构:

.venv/lib/python3.9/site-packages
??? bar
?   ??? __init__.py
?   ??? __pycache__
?       ??? __init__.cpython-39.pyc
??? baz
?   ??? __init__.py
?   ??? __pycache__
?       ??? __init__.cpython-39.pyc
??? foo
?   ??? __init__.py
?   ??? __pycache__
?       ??? __init__.cpython-39.pyc
??? mypackage-0.1.dist-info
    ??? INSTALLER
    ??? METADATA
    ??? RECORD
    ??? REQUESTED
    ??? WHEEL
    ??? direct_url.json
    ??? top_level.txt
Run Code Online (Sandbox Code Playgroud)

  • 再次感谢您的建议。我能够让 pacakge_dir 选项起作用,但只能用于一个目录。因为 package_dir 接受一个字典,键是一个空字符串(对于目标位置)和值是源目录,我似乎不能指定多个具有相同目标的源。.. 除非我遗漏了一些语法上的细微差别。再次感谢。 (2认同)
  • @chrisinmtown 是的,我认为它们都是需要的。`find_packages` 的一个优点是,如果您手动列出包,很容易忘记您需要添加子包 - 例如,如果有 `bar/subbar/__init__.py`,则必须列出两个“bar”和“bar.subbar”作为包。 (2认同)