【问题标题】:Run setup function from setuptools only if __name__ == "__main__"?仅当 __name__ == "__main__" 时才从 setuptools 运行设置功能?
【发布时间】:2023-03-30 05:25:01
【问题描述】:

只有在模块实际运行时,我才想在 setup.py 中运行 setup()。所以我想做这样的事情:

from setuptools import setup

def somefunction():
    ...

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

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

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

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

【问题讨论】:

  • 你试过了吗?
  • @MisterMiyagi 当然可以,但我的问题是这可能产生的任何意外后果,例如当 setup.py 在上下文中运行时,我不知道它可能在哪里,例如预计已经在导入时工作/运行。

标签: python python-3.x setuptools setup.py


【解决方案1】:

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

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

这可能吗?

是的。

不允许?

没有。

气馁?

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

为什么?

setup.py 的工作是从source distribution 句点安装您的代码。它通常不是其他随机任务的所在地,例如构建过程的文档。这个文件甚至不会包含在 wheel distribution 中,这可能是当今部署 Python 代码的更典型方式。

最后一点:如果并且当您使用 pyproject.toml 使用 声明性 构建系统转向现代 Python 打包实践时,将不会有 setup.py 脚本。那么无论如何,您将不得不为此类辅助功能找到一个新家。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      您可以采用不同的方式,将您感兴趣的所有功能添加到一个单独的模块中,该模块通常可由程序的其余部分导入。我不建议将包函数放入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
      

      【讨论】:

      • 只是为了澄清:我不是从我的包中导入,而是从 repo 中的另一个脚本导入,但不是包,它执行与文档相关的其他内务处理。跨度>
      • @Johsm。这使得这个功能更加有用
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-25
      • 2012-01-06
      • 1970-01-01
      • 2022-12-10
      • 1970-01-01
      相关资源
      最近更新 更多