13

假设我有一个对文件执行某些操作的脚本。它在命令行上使用此文件的名称,但如果未提供,则默认为已知文件名(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

4 回答 4

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.

于 2011-11-23T10:08:48.647 回答
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实现,并且将来可能会改变。但是,我不觉得它太乱,所以如果你认为维护风险得到回报,你仍然可能想使用它。

于 2011-11-23T09:35:49.163 回答
2

默认使用标准输入:

parser.add_argument('file', default='-', nargs='?', type=argparse.FileType('r'))
于 2016-10-22T20:32:24.233 回答
1

也许您可以定义自己的typeactionadd_argument检查文件是否存在的调用中,如果存在则返回文件句柄,否则返回None(或其他)。

不过,这也需要您自己编写一些代码,但如果不能始终使用默认值,您可能迟早需要进行一些检查。就像 Manny D 认为的那样,您可能需要重新考虑您的默认值。

于 2011-11-23T09:46:04.007 回答