10

我想以稍微不合常规的方式调用 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 的方式。

4

2 回答 2

15

从来没有尝试过,但我确实碰巧查看了 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']
)
于 2010-05-17T16:55:31.903 回答
2

只是“伪造”命令行参数——例如,开始你的脚本

import sys

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

from distutils.core import setup

setup(name='Distutils',

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

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

于 2010-05-18T05:12:12.323 回答