我有一个Python脚本,它读取包含某些其他工具的命令行调用的文件。我想在调用该工具之前修改此调用的选项。例如,我可能会改变:
my_util --input file1.txt --option1 red --option2 blue
......对此:
my_util --input file1_001.txt --option1 red --option3 green
(更准确地说,我将把这些论点作为列表来处理。)
我认为使用argparse
模块是最简单的方法:我可以根据需要解析args,更改,添加或删除选项,然后重新构建命令行。
但我该如何做最后一步?给定Namespace
返回的parse_args()
对象,我可以轻松地重建命令行选项列表,例如可以传递给subprocess.Popen()
吗?
答案 0 :(得分:2)
Namespace对象只是一个简单的对象子类,因此您可以使用vars
将值作为dict获取:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
>>> args = parser.parse_args(['--foo', 'BAR'])
>>> vars(args)
{'foo': 'BAR'}
或者你可以直接分配给一个类并将参数作为类变量输出:
>>> class C(object):
... pass
...
>>> c = C()
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
>>> parser.parse_args(args=['--foo', 'BAR'], namespace=c)
>>> c.foo
'BAR'
使用这些结构中的任何一个来测试/替换参数并将结果传递给Popen
是相当容易的。
答案 1 :(得分:0)
我知道这是一个老问题,但我刚刚遇到了同样的问题。我意识到我需要的只是一种迭代 Action 对象的方法。不幸的是,内部列表不是由 ArgParser 本身公开的。但是,这些对象由 add_argument()
返回,因此我可以构建自己的列表。好吧,在每个调用周围放置 actions.append()
对我来说似乎打字太多,所以我将所有选项存储在一个元组中:
def add_argument(*args, **kwargs):
return (args, kwargs)
parser = argparse.ArgumentParser()
options = (
add_argument('--verbose', action='store_true'),
add_argument('--author'),
add_argument('--subject', required=True),
add_argument('--cache', nargs='?'),
add_argument('files', nargs=''),
)
actions = []
for (args, kwargs) in options:
actions.append(parser.add_argument(*args, **kwargs))
args = parser.parse_args()
此时,选项在args
中解析,所有argparse.Action
对象都存储在actions
列表中。然后我可以遍历这个列表并重建如下选项:
cmdline = []
for action in actions:
value = getattr(args, action.dest)
if action.required or value != action.default:
if action.option_strings:
cmdline.append(action.option_strings[0])
if action.nargs is None:
cmdline.append(value)
elif action.nargs == '?':
if value != action.const:
cmdline.append(value)
elif action.nargs != 0:
cmdline += value
在我的特定情况下,我还想从命令行中删除一些选项。为此,我只是通过调用 parser.add_argument()
而不是通过 options
元组单独添加它们。