简体   繁体   English

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

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

I would like to run setup() in setup.py only if the module is actually run.只有当模块实际运行时,我才想在 setup.py 中运行 setup() 。 So I want to do something like:所以我想做一些类似的事情:

from setuptools import setup

def somefunction():
    ...

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

(I want to use some of the defined functions in the file, which are used in the setup() call, in another python script that is used during a documentation build process) (我想在文档构建过程中使用的另一个 python 脚本中使用文件中定义的一些函数,这些函数在 setup() 调用中使用)

Is this possible?这可能吗? Disallowed?不允许? Discouraged?灰心? Why?为什么?

I could not find any documentation about this, but oddly all examples do NOT use the test for " main ", so I wonder if there is anything that makes using this problematic.我找不到任何关于此的文档,但奇怪的是,所有示例都没有使用“ main ”的测试,所以我想知道是否有任何问题会导致使用这个问题。

The guards around the setup() call are not commonly seen in practice because this file is not usually imported . setup()调用周围的守卫在实践中并不常见,因为通常不会导入该文件。 It is well-known to be an installer script , intended to be executed directly.众所周知,它是一个安装程序脚本,旨在直接执行。

However, you may add the guards for the reason mentioned (" I want to use some of the defined functions in the file ") and everything within distutils/setuptools should still work fine.但是,您可以出于上述原因添加保护程序(“我想使用文件中的一些定义的函数”),并且 distutils/setuptools 中的所有内容仍然可以正常工作。 It is somewhat unusual for the setup.py script to have library functions defined within, so you may ask yourself whether there is a better home for such functions, rather than writing them directly in the installer script itself. setup.py脚本中定义了库函数有点不寻常,因此您可能会问自己是否有更好的方法来放置此类函数,而不是直接在安装程序脚本本身中编写它们。

Is this possible?这可能吗?

Yes.是的。

Disallowed?不允许?

No.不。

Discouraged?灰心?

Somewhat opinion-based.有点基于意见。 Personally, I would say yes: discourage that.就个人而言,我会说是:不鼓励这样做。

Why?为什么?

The job of setup.py is to install your code from a source distribution , period. setup.py的工作是从源代码分发版安装您的代码。 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 , which is probably the more typical way to deploy Python code these days.该文件甚至不会包含在wheel 发行版中,这可能是当今部署 Python 代码的更典型的方式。

As a final note: if and when you move toward modern Python packaging practices using pyproject.toml , with a declarative build-system, there will be no setup.py script.最后一点:如果您使用pyproject.toml转向现代 Python 打包实践,并使用声明性构建系统,则不会有setup.py脚本。 Then you are going to have to find a new home for such helper functions anyway.那么无论如何你都必须为这些辅助函数找到一个新家。

Shouldn't be a problem.应该不是问题。 I would recommend always using the if __name__ == "__main__": condition even if there the module is never imported.我建议始终使用if __name__ == "__main__":条件,即使从未导入模块也是如此。 What I would not recommend on the other hand tough, is to share code between the setup script and the code of the project itself.另一方面,我不建议在安装脚本和项目本身的代码之间共享代码。

You can go a different route, and add all your functions of interest to a separate module that's normally importable by the rest of your program.您可以采用不同的方法,将您感兴趣的所有功能添加到通常可由程序的其余部分导入的单独模块中。 I wouldn't recommend putting package functions into setup.py because the setup file is meant to live outside your package.我不建议将包函数放入setup.py因为安装文件旨在存在于您的包之外。 You may need a utility function to import the module by path in setup.py .您可能需要一个实用函数来通过setup.py的路径导入模块。 I generally use something that looks like this:我通常使用看起来像这样的东西:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM