使用argparse指定默认文件名,但在--help时不打开它们?
假设我有一个脚本,它会对一个文件进行一些操作。这个脚本可以在命令行中接收文件名,如果没有提供文件名,它会默认使用一个已知的文件名(比如说content.txt
)。我使用Python的argparse
模块来实现这个功能:
parser = argparse.ArgumentParser(description='my illustrative example')
parser.add_argument('--content', metavar='file',
default='content.txt', type=argparse.FileType('r'),
help='file to process (defaults to content.txt)')
args = parser.parse_args()
# do some work on args.content, which is a file-like object
这个方法很好用。唯一的问题是,如果我运行python myscript --help
,如果文件不存在,就会出现一个ArgumentError
错误(我想这也算合理),而帮助信息就不会显示出来。我希望在用户只想要--help
的时候,不要去尝试打开文件。有没有办法做到这一点?我知道我可以把这个参数设置为字符串,然后自己处理打开文件的事情(我一直都是这么做的),但如果能让argparse
来处理这个就方便多了。
4 个回答
2
将标准输入作为默认输入:
parser.add_argument('file', default='-', nargs='?', type=argparse.FileType('r'))
13
你可以通过创建一个新的类来扩展 argparse.FileType
:
import argparse
import warnings
class ForgivingFileType(argparse.FileType):
def __call__(self, string):
try:
super(ForgivingFileType,self).__call__(string)
except IOError as err:
warnings.warn(err)
parser = argparse.ArgumentParser(description='my illustrative example')
parser.add_argument('--content', metavar='file',
default='content.txt', type=ForgivingFileType('r'),
help='file to process (defaults to content.txt)')
args = parser.parse_args()
这样做就不需要修改像 ArgumentParser._parse_known_args
这样的私有方法。
10
看一下argparse的代码,我发现:
ArgumentParser.parse_args
会调用parse_known_args
,并确保没有待解析的参数。ArgumentParser.parse_known_args
会设置默认值,然后调用ArgumentParser._parse_known_args
所以,解决方法就是直接使用ArgumentParser._parse_known_args
来检测-h
,然后再像往常一样使用ArgumentParser.parse_args
。
import sys, argparse
parser = argparse.ArgumentParser(description='my illustrative example', argument_default=argparse.SUPPRESS)
parser.add_argument('--content', metavar='file',
default='content.txt', type=argparse.FileType('r'),
help='file to process (defaults to content.txt)')
parser._parse_known_args(sys.argv[1:], argparse.Namespace())
args = parser.parse_args()
需要注意的是,ArgumentParser._parse_known_args
需要两个参数:来自命令行的参数和命名空间。
当然,我不建议使用这种方法,因为它利用了argparse的内部实现,而这些实现将来可能会改变。不过,我觉得这并不是太复杂,所以如果你认为维护的风险是值得的,还是可以考虑使用。