5

argparse用于验证文件名 cmd 行参数的文件扩展名?

例如,如果我有一个从 cmd 行运行的 python 脚本:

$ script.py file.csv
$ script.py file.tab
$ script.py file.txt

我希望 argparse 接受第一个两个文件名 cmd 行选项,但拒绝第三个

我知道你可以这样做:

parser = argparse.ArgumentParser()
parser.add_argument("fn", choices=["csv","tab"])
args = parser.parse_args()

为 cmd 行选项指定两个有效选项

我想要的是这样的:

parser.add_argument("fn", choices=["*.csv","*.tab"])

为 cmd 行选项指定两个有效的文件扩展名。不幸的是,这不起作用 - 有没有办法使用argparse

4

3 回答 3

9

当然——你只需要指定一个适当的函数作为type.

import argparse
import os.path

parser = argparse.ArgumentParser()

def file_choices(choices,fname):
    ext = os.path.splitext(fname)[1][1:]
    if ext not in choices:
       parser.error("file doesn't end with one of {}".format(choices))
    return fname

parser.add_argument('fn',type=lambda s:file_choices(("csv","tab"),s))

parser.parse_args()

演示:

temp $ python test.py test.csv
temp $ python test.py test.foo
usage: test.py [-h] fn
test.py: error: file doesn't end with one of ('csv', 'tab')

这是一种可能更干净/更通用的方法:

import argparse
import os.path

def CheckExt(choices):
    class Act(argparse.Action):
        def __call__(self,parser,namespace,fname,option_string=None):
            ext = os.path.splitext(fname)[1][1:]
            if ext not in choices:
                option_string = '({})'.format(option_string) if option_string else ''
                parser.error("file doesn't end with one of {}{}".format(choices,option_string))
            else:
                setattr(namespace,self.dest,fname)

    return Act

parser = argparse.ArgumentParser()
parser.add_argument('fn',action=CheckExt({'csv','txt'}))

print parser.parse_args()

这里的缺点是代码在某些方面变得有点复杂——结果是当你真正去格式化你的参数时,界面变得更干净了。

于 2013-03-04T14:34:20.930 回答
7

定义一个将名称作为字符串的自定义函数 - 将扩展名分开以进行比较,如果没问题就返回字符串,否则会引发 argparse 期望的异常:

def valid_file(param):
    base, ext = os.path.splitext(param)
    if ext.lower() not in ('.csv', '.tab'):
        raise argparse.ArgumentTypeError('File must have a csv or tab extension')
    return param

然后使用该功能,例如:

parser = argparse.ArgumentParser()
parser.add_argument('filename', type=valid_file)
于 2013-03-04T14:36:58.147 回答
-3

不,您可以为选择参数或任何支持“in”运算符的容器对象提供容器对象。您可以在pydocs阅读更多内容

您可以随时自行检查并向用户提供反馈。

于 2013-03-04T14:33:44.250 回答