Python 如何打包导入产生副作用的库?

How to package a library whose import produces side effects in Python?

我正在开发一个 python 库(不是我的),它看起来像这样:

.
├── README.md
├── setup.py
└── library
    ├── __init__.py
    ├── core.py
    ├── a.py
    └── b.py

文件 __init__.py 使用 core.py,它本身使用 a.pyb.py。需要注意的重要一点是 import library 有一些故意设计的副作用。

但是,我想让用户可以使用 core.py 的功能而不会有任何副作用。不幸的是,如您所知,import library.corefrom library import core 无论如何都会执行 __init__.py(发生副作用的地方)。

你知道我如何重组我的包和 setup.py 来解决这个问题吗?


我想到了这样的事情:

.
├── README.md
├── setup.py
├── library_core
│   ├── __init__.py
│   ├── core.py
│   ├── a.py
│   └── b.py
└── library
    └── __init__.py  # Import library_core and apply side effects

我会将 setup.py 更新为 packages = ['library', 'library_core']。这样,导入 library 不会改变任何东西,但用户可以导入 library_core 而没有任何副作用。此外,这将避免重复代码,所有内容都将保留在同一个存储库中。

不幸的是,这不起作用,因为我无法从 library 导入 library_core,因为它们不在文件树中的同一位置。

我建议您停止依赖副作用并要求用户通过调用已记录的函数来显式触发它们。否则你就是在打一场必败仗:目前默认是触发副作用,然后如果用户不想要它们,你必须撤消它们。

使用两个包似乎是最好的方法。

只有安装了整个库(例如python setup.py install),才能使用两个相邻的包。这使开发变得相当复杂,例如对于单元测试:然后无法执行 import library,因为如果未安装则无法找到 library_core

因此,最好的解决方案是简单地制作一个子包,并在 setup.py 中指定 library_core 所在的位置,这要归功于 package_dir 选项。

文件树看起来像这样:

.
├── README.md
├── setup.py
└── library
    ├── __init__.py
    └── core
        ├── __init__.py
        ├── a.py
        └── b.py

setup.py中:

setup(
    name = 'library',
    packages = ['library', 'library.core', 'library_core'],
    package_dir = {'library_core': 'library/core'},
    ...
)