1

我有一个根据某些参数运行的 python 程序。比方说,其中一个参数C的默认值为3. 所以当我在没有任何参数的情况下运行它时,它确实

$ python parsing.py
C=3

当我为我的初始数据加载一个文件时,它可以从该文件中获取一些参数值。例如,如果我的文件MakeC5说程序应该运行C=5,我会得到

$ python parsing.py --file=MakeC5
C=5

另一方面,如果我为 C 指定一个不同的值作为可选参数,则采用该值,并优先于文件中的值。

$ python parsing.py --C=4
C=4

$ python parsing.py --file=MakeC5 --C=4
C=4

到这里为止,我可以只检查命令行上指定的值是否与默认值不同,否则从文件中获取一个,如

if parameters.C == parser.get_default('C'):
    parameters.C = load_file(parameters.file)["C"]

但是,如果我在命令行上为 C 提供默认值,则这种方法不起作用,如

$ python parsing.py --file=MakeC5 --C=3
C=3

我怎样才能把那个案子弄好?有没有一种方法不需要像在

parameters = parser.parse_args()
parameters_from_file = load_file(parameters.file)
parser.set_defaults(**parameters_from_file)
parameters = parser.parse_args()

对我来说,这看起来不像“明显的 pythonic 方式”?这是准读取一个可以指定为参数的配置文件,所以我希望有一个好方法。

4

2 回答 2

5

假设您使用argparsemodule,只需在添加参数时不要设置默认参数。如果参数不存在,则属性将是None,您可以检查它而不是解析参数两次:

parser.add_argument('--C'   , action='store', dest='C')
parser.add_argument('--file', action='store', dest='file')
# ...

args = parser.parse_args()
# ...

if args.C is None:
    # Argument `--C` not given on command line
    if args.file is not None:
        # Load the file, set `args.C` if the file contains the `C` option
        ...

if args.C is None:
    # `C` was neither specified on the command line argument given,
    # nor in the configuration file, set default value
    args.C = 3

print 'C =', args.C
于 2013-02-13T13:38:53.587 回答
1

argsparse中有fromfile-prefix-chars,如果你能忍受它的限制,它似乎可以做一些你想做的事情。

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', default="ABC")
args = parser.parse_args()
print '#1', args.foo

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', default="ABC")
args = parser.parse_args(['--foo', 'BAR' ])
print '#2', args.foo

import argparse
parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
parser.add_argument('--foo', default="ABC")
args = parser.parse_args(['--foo', 'BAR', '@myargs' ])
print '#3', args.foo

import argparse
parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
parser.add_argument('--foo', default="ABC")
args = parser.parse_args(['@myargs', '--foo', 'BAR' ])
print '#4', args.foo

迈尔格斯

--foo
FISH

输出

#1 ABC
#2 BAR
#3 FISH
#4 BAR

请注意@myargs 在命令行上的位置如何影响 的值foo,当它位于前面时,如果被覆盖,则它被赋值--foo ,反之亦然。

这似乎可以满足您的要求:

默认值 < 配置文件 < cli-args

尽管它依赖于您记住将配置文件以正确的顺序放置,但当然除非您获取 args 并重新排序它们,以便它们在 args 中排在首位。

希望值得深思。

于 2013-02-13T15:05:48.423 回答