Directly call distutils' or setuptools' setup() function with command name/options, without parsing the command line?
I'd like to call Python's distutils' or setuptools' setup() function in a slightly unconventional way, but I'm not sure whether distutils is meant for this kind of usage.
As an example, let's say I currently have a 'setup.py' file, which looks like this (lifted verbatim from the distutils docs--the setuptools usage is almost identical):
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'],
)
Normally, to build just the .spec file for an RPM of this module, I could run python setup.py bdist_rpm --spec-only
, which parses the command line and calls the 'bdist_rpm' code to handle the RPM-specific stuff. The .spec file ends up in './dist'.
How can I change my setup() invocation so that it runs the 'bdist_rpm' command with the '--spec-only' option, WITHOUT parsing command-line parameters? Can I pass the command name and options as parameters to setup()? Or can I manually construct a command line, and pass that as a parameter, instead?
NOTE: I already know that I could call the script in a separate process, with an actual command line, using os.system() or the subprocess module or something similar. I'm trying to avoid using any kind of external command invocations. I'm looking specifically for a solution that runs setup() in the current interpreter.
For background, I'm converting some release-management shell scripts into a single Python program. One of the tasks is running 'setup.py' to generate a .spec file for further pre-release testing. Running 'setup.py' as an external command, with its own command line options, seems like an awkward method, and it complicates the rest of the program. I feel like there may be a more Pythonic way.
Never tried this, but I did happen to look in distutils/core.py, where I notice this near the start of 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:]
So, it looks as if you can "fake-out" setup() by adding:
setup(
...
script_name = 'setup.py',
script_args = ['bdist_rpm', '--spec-only']
)
Just "fake" the commandline parameters -- e.g, start you script with
import sys
sys.argv[1:] = ['bdist_rpm', '--spec-only']
from distutils.core import setup
setup(name='Distutils',
etc, etc. After all, that's how distutils
gets the command line parameters: it looks in sys.argv
! So, just set sys.argv
to be exactly as you want it, and whatever command line the misguided user typed will be completely ignored.
Actually, you might want to check if the user did enter any argument you're about to ignore -- len(sys.argv) > 1
before you modify sys.argv
-- and give a warning, or avoid the alteration of sys.argv, or "merge" what the user typed, etc... but that's quite different from what you actually asked, so I'm going to leave it at that;-).
精彩评论