【问题标题】:Directly call distutils' or setuptools' setup() function with command name/options, without parsing the command line?直接用命令名/选项调用distutils'或setuptools'setup()函数,不解析命令行?
【发布时间】:2011-02-20 12:19:20
【问题描述】:

我想以稍微不合常规的方式调用 Python 的 distutils 或 setuptools 的 setup() 函数,但我不确定 distutils 是否适合这种用法。

例如,假设我目前有一个“setup.py”文件,它看起来像这样(从 distutils 文档中逐字删除——setuptools 的用法几乎相同):

from distutils.core import setup

setup(name='Distutils',
      version='1.0',
      description='Python Distribution Utilities',
      author='Greg Ward',
      author_email='gward@python.net',
      url='http://www.python.org/sigs/distutils-sig/',
      packages=['distutils', 'distutils.command'],
     )

通常,要仅为该模块的 RPM 构建 .spec 文件,我可以运行 python setup.py bdist_rpm --spec-only,它会解析命令行并调用“bdist_rpm”代码来处理特定于 RPM 的内容。 .spec 文件以 './dist' 结尾。

如何更改我的 setup() 调用,使其运行带有“--spec-only”选项的“bdist_rpm”命令,而不解析命令行参数?我可以将命令名称和选项作为参数传递给 setup() 吗?或者我可以手动构建一个命令行,并将其作为参数传递吗?

注意:我已经知道我可以在单独的进程中调用脚本,使用实际的命令行,使用 os.system() 或 subprocess 模块或类似的东西。我试图避免使用任何类型的外部命令调用。我正在专门寻找在当前解释器中运行 setup() 的解决方案。

作为背景,我正在将一些发布管理 shell 脚本转换为单个 Python 程序。其中一项任务是运行“setup.py”以生成 .spec 文件以进行进一步的预发布测试。将“setup.py”作为外部命令运行,并带有自己的命令行选项,这似乎是一种尴尬的方法,并且会使程序的其余部分复杂化。我觉得可能有一种更 Pythonic 的方式。

【问题讨论】:

  • 我喜欢这个问题。对我来说,setup() 的设计似乎很糟糕——它至少应该将sys.argv 作为参数而不是执行一些魔法。该参数甚至可以默认为sys.argv(如argparse),但应该在函数签名中记录和可见。

标签: python setuptools distutils


【解决方案1】:

从未尝试过,但我确实碰巧查看了 distutils/core.py,我在 setup() 的开头附近注意到了这一点:

if 'script_name' not in attrs:
    attrs['script_name'] = os.path.basename(sys.argv[0])
if 'script_args' not in attrs:
    attrs['script_args'] = sys.argv[1:]

因此,您似乎可以通过添加以下内容来“伪造”setup():

setup(
    ...
    script_name = 'setup.py',
    script_args = ['bdist_rpm', '--spec-only']
)

【讨论】:

  • @ig0775:谢谢,这正是我想做的。我刚刚测试了它,它工作正常。看起来也很干净。
  • 这花了我2天的时间搜索......终于在这里找到了这个答案,非常感谢;)
【解决方案2】:

只是“伪造”命令行参数——例如,用

开始你的脚本
import sys

sys.argv[1:] = ['bdist_rpm', '--spec-only']

from distutils.core import setup

setup(name='Distutils',

等等等等。毕竟,distutils 就是这样获取命令行参数的:它在sys.argv 中查找!因此,只需将sys.argv 设置为您想要的那样,任何被误导的用户键入的命令行都将被完全忽略。

实际上,您可能想检查用户是否确实在您修改sys.argv之前输入了您将要忽略的任何参数——len(sys.argv) > 1——并给出警告,或者避免sys.argv 的更改,或“合并”用户键入的内容等...但这与您实际询问的内容完全不同,所以我将保留它;-)。

【讨论】:

  • 这件事发生在我身上,但看起来有点乱。但如果不是@ig0774的方法,我可能会这样处理。
  • @RyanB.Lynch:看起来有点乱 – 可悲、可悲的是:Distutils 和 Setup Tools 的 run_setup 例程正是这样做的,只有一些结冰在上面。您可以在源代码中看到这一点,例如 here(搜索 run_setup)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
  • 2015-01-15
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
  • 2012-08-18
  • 1970-01-01
相关资源
最近更新 更多