使用命令名/选项直接调用distutils'或setuptools'setup()函数,而无需解析命令行?

时间:2010-05-17 16:45:49

标签: python setuptools distutils

我想以一种略微不同寻常的方式调用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()或子进程模块或类似的东西来调用脚本。我试图避免使用任何类型的外部命令调用。我正在寻找一种在当前解释器中运行setup()的解决方案。

对于后台,我正在将一些发布管理shell脚本转换为单个Python程序。其中一项任务是运行'setup.py'来生成.spec文件,以进行进一步的预发布测试。运行'setup.py'作为外部命令,使用自己的命令行选项,似乎是一个尴尬的方法,它使程序的其余部分复杂化。我觉得可能有更多的Pythonic方式。

2 个答案:

答案 0 :(得分:11)

从未尝试过这个,但我确实碰巧在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']
)

答案 1 :(得分: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,或“合并”用户输入的内容等等......但这与你实际要求的完全不同,所以我将把它留在那里; - )。