Python argparse 文件保存方法

12

Argparse有一个名为fromfile-prefix-chars的特性,看起来正好做到了我要找的一半。我该如何从当前命令行参数创建此特性所需的文件?

我有一个复杂的脚本,其中解析器自动化了代码构建的一部分。使用案例是第一次正确设置命令行,然后基本上使用相同的参数重新运行。

使用文件并从中加载似乎是实现我所需的功能的好方法。似乎缺少的是一种简单的方法将初始命令行写入文件,以便现有的文件解析将正常工作。

2个回答

27
from argparse import ArgumentParser
import json

parser = ArgumentParser()
parser.add_argument('--seed', type=int, default=8)
parser.add_argument('--resume', type=str, default='a/b/c.ckpt')
parser.add_argument('--surgery', type=str, default='190', choices=['190', '417'])
args = parser.parse_args()

with open('commandline_args.txt', 'w') as f:
    json.dump(args.__dict__, f, indent=2)

parser = ArgumentParser()
args = parser.parse_args()
with open('commandline_args.txt', 'r') as f:
    args.__dict__ = json.load(f)

print(args)

11

文件格式已经被清楚地文档化:

从文件中读取的参数默认每行一个 [...]

文档中的代码示例也展示了在每行之间加入换行符的写入文件方式:

>>> with open('args.txt', 'w') as fp:
...     fp.write('-f\nbar')
如果您想保存当前的命令行,请将sys.argv [1:]写入文件,参数之间使用换行符分隔:
with open('commandline_args.txt', 'w') as f:
    f.write('\n'.join(sys.argv[1:]))

演示:

>>> from argparse import ArgumentParser
>>> import sys
>>> parser = ArgumentParser(fromfile_prefix_chars='@')
>>> parser.add_argument('--foo')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('bar', nargs='?')
_StoreAction(option_strings=[], dest='bar', nargs='?', const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> sys.argv[1:] = ['--foo', 'spam', 'barbaz']
>>> parser.parse_args()
Namespace(bar='barbaz', foo='spam')
>>> with open('commandline_args.txt', 'w') as f:
...     f.write('\n'.join(sys.argv[1:]))
...
17
>>> parser.parse_args(['@commandline_args.txt'])
Namespace(bar='barbaz', foo='spam')
>>> sys.argv[1:] = ['--foo=spam', 'barbaz']  # using alternate syntax
>>> parser.parse_args()
Namespace(bar='barbaz', foo='spam')
>>> with open('commandline_args.txt', 'w') as f:
...     f.write('\n'.join(sys.argv[1:]))
...
17
>>> parser.parse_args(['@commandline_args.txt'])
Namespace(bar='barbaz', foo='spam')

我不认为这是那么简单的。请参考 https://dev59.com/I4Lba4cB1Zd3GeqPZxlL#25084994。你的解决方案会将标志和标志值分开放在两行中。 - Brett Stottlemyer
1
@BrettStottlemyer:是的,那很好。请注意,文档中的代码示例正是如此 - Martijn Pieters
@BrettStottlemyer:请注意,它们在sys.argv中是单独的参数条目。您可以使用一个字符串'--option=foo'或者在sys.argv列表中使用'--option''foo'两个参数。 - Martijn Pieters
@BrettStottlemyer:最后但并非最不重要的一点是,请注意您链接到文件的问题没有拆分为单独的行。如果--option1foo在单独的行上,或者您在开关和值之间使用=,那么该问题将起作用。 - Martijn Pieters
@BrettStottlemyer:我添加了一个演示会话,展示了两种表单。 - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接