使用argparse指定默认文件名,但不能在--help上打开它们?

Ism*_*awi 12 python argparse

假设我有一个脚本可以对文件进行一些操作.它在命令行中使用此文件的名称,但如果未提供,则默认为已知文件名(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
Run Code Online (Sandbox Code Playgroud)

这非常有效.唯一的问题是,如果我运行python myscript --help,我得到一个ArgumentError如果文件不存在(我猜有意义),并且不显示帮助文本.我宁愿它不试图打开文件,如果用户只是想要--help.有没有办法做到这一点?我知道我可以把参数作为一个字符串,并在以后自己打开文件(我一直这样做),但是argparse照顾它会很方便.

unu*_*tbu 12

你可以继承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()
Run Code Online (Sandbox Code Playgroud)

这工作无需像私人方法那样触摸ArgumentParser._parse_known_args.


jco*_*ado 9

看一下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()
Run Code Online (Sandbox Code Playgroud)

请注意,ArgumentParser._parse_known_args需要几个参数:命令行和命名空间中的参数.

当然,我不推荐这种方法,因为它利用了内部argparse实现,并且可能在将来发生变化.但是,我并不觉得它太乱,所以如果您认为维护风险得到回报,您仍然可能想要使用它.