Python 使用argparse指定文件扩展名
我想用argparse指定几个文件扩展名 我已经尝试了下面的代码,但它不工作。如何使用argparse指定多个文件扩展名Python 使用argparse指定文件扩展名,python,argparse,file-extension,Python,Argparse,File Extension,我想用argparse指定几个文件扩展名 我已经尝试了下面的代码,但它不工作。如何使用argparse指定多个文件扩展名 parser.add_argument('file', action = 'store', type = argparse.FileType('r'), choices=["*.aaa", "*.bbb"]) 编辑:我使用字符串类型而不是文件类型找到了自己的解决方案: def input_ok(string): if not os.path.exists(strin
parser.add_argument('file', action = 'store', type = argparse.FileType('r'), choices=["*.aaa", "*.bbb"])
编辑:我使用字符串类型而不是文件类型找到了自己的解决方案:
def input_ok(string):
if not os.path.exists(string):
raise argparse.ArgumentTypeError("Filename %r doesn\'t exists in this directory." % string)
if string[-4:] != ".aaa" and string[-4:] != ".bbb":
raise argparse.ArgumentTypeError("%r is not a .aaa or a .bbb file." % string)
return string
问题的关键是如何工作。Argparse首先构建一个传递参数的列表并进行类型转换,然后使用
in
操作符检查选项中是否包含参数。这意味着它不会进行任何模式匹配(匹配'*.aaa'
),而是检查字符串是否相等。相反,我们可以制作自己的容器来传递选择
如果不使用argparse.Filetype
,它看起来是这样的。Argparse还需要容器具有\uuuuu iter\uuuu
,以生成帮助消息的Metavar元组
class Choices():
def __init__(self, *choices):
self.choices = choices
def __contains__(self, choice):
# True if choice ends with one of self.choices
return any(choice.endswith(c) for c in self.choices)
def __iter__(self):
return iter(self.choices)
parser.add_argument('file', action='store', choices=Choices('.aaa', '.bbb'))
通过更改\uuuu包含的内容来满足您的需要,您可以将此想法扩展到几乎任何事情。例如,如果您还传递了type=argparse.FileType('r')
,则argparse将在检查包含之前转换为文件对象
def __contains__(self, choice):
# choice is now a file object
return any(choice.name.endswith(c) for c in self.choices)
顺便说一句,这就是我讨厌argparse的原因。它过于复杂,并且试图做得比它应该做的更多。我认为不应该在参数解析器中进行验证。自己使用并验证东西。接受字符串,然后自己进行验证没有什么错。有时,您需要检查文件名是否正确,但要等到以后才能打开它(例如,将打开(文件名)作为f:
)使用)。这可能是最简单的方法
kalhartt的
选项
类的另一种选择是使用os.path
或glob
获取允许文件的列表
p.add_argument('file',choices=glob.glob('*.txt'))
In [91]: p.parse_args('test.txt'.split())
Out[91]: Namespace(file='test.txt')
这样做的一个问题是,帮助和错误消息可能过长,列出了所有允许的文件名
此选项
不适用于文件类型
。这是因为在打开文件后,它会根据选项进行测试
p.add_argument('file',choices=[open('test.txt')],type=argparse.FileType('r'))
p.parse_args('test.txt'.split())
# usage: python [-h] {<open file 'test.txt', mode 'r' at 0xa102f98>}
# error: argument file: invalid choice: <open file 'test.txt', mode 'r' at 0xa102f40>
# (choose from <open file 'test.txt', mode 'r' at 0xa102f98>)
argparse
为您提供了一些参数验证工具,但不要求您使用它们<代码>文件类型
是一种方便的功能,用于常见的脚本应用程序。如果它不适合您的应用程序,您不必使用它。选项也是如此。
p.add_argument('file',choices=[open('test.txt')],type=argparse.FileType('r'))
p.parse_args('test.txt'.split())
# usage: python [-h] {<open file 'test.txt', mode 'r' at 0xa102f98>}
# error: argument file: invalid choice: <open file 'test.txt', mode 'r' at 0xa102f40>
# (choose from <open file 'test.txt', mode 'r' at 0xa102f98>)
class FileTypeWithExtension(argparse.FileType):
def __init__(self, mode='r', bufsize=-1, extension=None):
self._extension = extension
super(FileTypeWithExtension, self).__init__()
def __call__(self, string):
if string != '-' and self._extension:
if not string.endswith(self._extension):
# just testing against one extension for now
raise argparse.ArgumentTypeError('wrong extension')
return super(FileTypeWithExtension, self).__call__(string)
p.add_argument('file',type=FileTypeWithExtension('r',extension='txt'))
p.parse_args('test.tst'.split())
#usage: ipython [-h] file
#ipython: error: argument file: wrong extension
p.parse_args('test.txt'.split())
# Namespace(file=<open file 'test.txt', mode 'r' at 0xa13ce90>)