运行 仅当 __name__ == “__main__” 时才从 setuptools 设置函数?

Run setup function from setuptools only if __name__ == "__main__"?

我想在 setup.py 中 运行 setup() 仅当模块实际上是 运行 时。所以我想做类似的事情:

from setuptools import setup

def somefunction():
    ...

if __name__ == "__main__":
    setup(...)

(我想在文档构建过程中使用的另一个 python 脚本中使用文件中的一些已定义函数,这些函数在 setup() 调用中使用)

这可能吗?不允许?灰心?为什么?

我找不到任何关于此的文档,但奇怪的是所有示例都没有使用“main”的测试,所以我想知道是否有任何问题导致使用此问题.

应该没有问题。我建议始终使用 if __name__ == "__main__": 条件,即使从未导入该模块。另一方面,我不建议在设置脚本和项目本身的代码之间共享代码。

setup() 调用周围的守卫在实践中并不常见,因为这个文件通常不会 导入 。众所周知是一个安装程序脚本,旨在直接执行。

但是,您可以出于上述原因(“我想使用文件中定义的一些函数”)以及 distutils/setuptools 中的所有内容添加守卫应该仍然可以正常工作。 setup.py 脚本在其中定义库函数有点不寻常,因此您可能会问自己是否有更好的归宿来放置这些函数,而不是直接在安装程序脚本本身中编写它们。

Is this possible?

是的。

Disallowed?

没有

Discouraged?

有点基于意见。就个人而言,我会说是:不鼓励这样做。

Why?

setup.py 的工作是从 source distribution, period. It is not typically the home for other random tasks such as documentation of build process. This file will not even be included in a wheel distribution 安装您的代码,这可能是目前部署 Python 代码的更典型方式。

作为最后的说明:如果并且当您转向使用 pyproject.toml 的现代 Python 打包实践时,使用 声明式 构建系统,将会是没有setup.py脚本。那么你将不得不为这些辅助函数找到一个新家。

您可以走不同的路线,将您感兴趣的所有功能添加到一个单独的模块中,该模块通常可由您的程序的其余部分导入。我不建议将包函数放入 setup.py 中,因为安装文件应该存在于你的包之外。您可能需要一个实用函数来通过 setup.py 中的路径导入模块。我通常使用如下所示的东西:

def import_file(name, location):
    """
    Imports the specified python file as a module, without explicitly
    registering it to `sys.modules`.
    """
    if sys.version_info[0] == 2:
        # Python 2.7-
        from imp import load_source
        mod = load_source(name, location)
    elif sys.version_info < (3, 5, 0):
        # Python 3.4-
        from importlib.machinery import SourceFileLoader
        mod = SourceFileLoader(name, location).load_module()
    else:
        # Python 3.5+
        from importlib.util import spec_from_file_location, module_from_spec
        spec = spec_from_file_location(name, location)
        mod = module_from_spec(spec)
        spec.loader.exec_module(mod)
    return mod