python argparse.FileType(' w')检查扩展名

时间:2018-01-19 17:45:16

标签: python argparse file-type

argparse 包在处理命令行参数时表现非常出色。我想知道是否有任何方法要求argparse检查文件扩展名(例如" .txt")。我们的想法是派生一个与 argparse.FileType 相关的类。我会对任何建议感兴趣。

请记住,我的程序中有超过50个子命令,都有自己的CLI。因此,我有兴趣派生一个可以在每个中导入的类,而不是在我的所有命令中添加一些uggly测试。

非常感谢。

# As an example one would be interested in turning this...
parser_grp.add_argument('-o', '--outputfile',
                        help="Output file.",
                        default=sys.stdout,
                        metavar="TXT",
                        type=argparse.FileType('w'))


# Into that...
from somewhere import FileTypeWithExtensionCheck 
parser_grp.add_argument('-o', '--outputfile',
                        help="Output file.",
                        default=sys.stdout,
                        metavar="TXT",
                        type=FileTypeWithExtensionCheck('w', '.[Tt][Xx][Tt]$'))

2 个答案:

答案 0 :(得分:4)

您可以继承argparse.FileType() class,并覆盖G4方法进行文件名验证:

__call__

如果你真的想要,你也可以支持正则表达式,但使用class FileTypeWithExtensionCheck(argparse.FileType): def __init__(self, mode='r', valid_extensions=None, **kwargs): super().__init__(mode, **kwargs) self.valid_extensions = valid_extensions def __call__(self, string): if self.valid_extensions: if not string.endswith(self.valid_extensions): raise argparse.ArgumentTypeError( 'Not a valid filename extension') return super().__call__(string) 是一种更常见,更简单的测试。

这需要单个字符串或指定有效扩展名的字符串元组:

str.endswith()

您需要在parser_grp.add_argument( '-o', '--outputfile', help="Output file.", default=sys.stdout, metavar="TXT", type=argparse.FileTypeWithExtensionCheck('w', valid_extensions=('.txt', '.TXT', '.text')) ) 方法中处理此问题,因为__call__实例基本上与任何其他FileType()参数一样对待;作为 callable ,您可以通过引发type=异常来指示特定参数不适合。

答案 1 :(得分:1)

我的解决方案是创建一个执行扩展检查的闭包:

import argparse

def ext_check(expected_extension, openner):
    def extension(filename):
        if not filename.lower().endswith(expected_extension):
            raise ValueError()
        return openner(filename)
    return extension

parser = argparse.ArgumentParser()
parser.add_argument('outfile', type=ext_check('.txt', argparse.FileType('w')))

# test out
args = parser.parse_args()
args.outfile.write('Hello, world\n')

注释

  • ext_check基本上是argparse.FileType
  • 的包装器
  • 需要预期的延期检查和开放式
  • 为简单起见,预期的扩展名为小写,文件名将在验证前转换为小写
  • 在这种情况下,
  • opennerargparse.FileType('w')可调用的(很可能是一个函数,但我不在乎,只要它是可调用的)。
  • ext_check返回一个callable,这是一个名为extension的函数。我这样命名,所以错误将如下所示(请注意 extension 这个词,这是函数的名称):

    error: argument outfile: invalid extension value: 'foo.txt2'
    
  • extension函数中,我们检查文件扩展名,如果通过,我们将文件名传递给openner

我喜欢这个解决方案

  • 简明
  • 几乎不需要知道argparse.FileType如何工作,因为它只是作为它的包装

我不喜欢它

  • 调用者必须了解关闭以了解其工作原理
  • 我无法控制错误消息。这就是为什么我必须命名我的内部函数extension以获得如上所示的有意义的错误消息。

其他可能的解决方案

  • 创建自定义操作,请参阅argparse
  • 的文档
  • Martijn Pieters完成的子类argparse.FileType

这些解决方案中的每一个都有自己的优点和缺点