python argparse文件扩展名检查

python argparse文件扩展名检查,python,argparse,Python,Argparse,是否可以使用argparse验证filename cmd行参数的文件扩展名 e、 g.如果我有一个python脚本,我从cmd行运行: $ script.py file.csv $ script.py file.tab $ script.py file.txt 我希望argparse接受前两个filename cmd行选项,但拒绝第三个选项 我知道你可以这样做: parser = argparse.ArgumentParser() parser.add_argument("fn", choic

是否可以使用
argparse
验证filename cmd行参数的文件扩展名

e、 g.如果我有一个python脚本,我从cmd行运行:

$ script.py file.csv
$ script.py file.tab
$ script.py file.txt
我希望argparse接受前两个filename 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
实现这一点?

否。您可以向choices参数或任何支持“in”运算符的对象提供容器对象。你可以在

您可以自己检查并向用户提供反馈。

当然——您只需要指定一个适当的函数作为
类型

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()
演示:


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

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()

这里的缺点是代码在某些方面变得更复杂了——结果是,当您实际格式化参数时,接口变得更干净了。

定义一个将名称作为字符串的自定义函数-拆分扩展名以进行比较,如果可以的话,只返回字符串,否则引发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)

嗯。。。。
notcsv
的输入名称不正确?这还取决于作为全局的
parser
,而我认为引发异常是正确的方法……我想到了。。。但我想让这个例子保持简单。。。我想你可以做
文件选择(('.csv','.tab))
这很好。或者,如果ext不在选项中,您可以将检查更改为
ext
os.path.splitext(fname)[1]
或其他任何内容…Jon Clements和mgilson的答案现在看起来很相似-在这里使用lambda有好处吗它似乎比JonI的等效答案稍微复杂一些,JonI会说,主要区别在于该方法要求
解析器
是函数范围内的全局变量(因为它使用了
parser.error
——我避免了这种情况,而是从模块中引发了异常…@Hiett——它允许我使用相同的函数检查多个命令行参数(例如,如果您有一个地方需要检查
.txt
.csv
,另一个地方需要检查
.xls
.doc
——否则没有太大区别。所以您会在parser.parse_args()之前调用有效的_文件。)?
parser = argparse.ArgumentParser()
parser.add_argument('filename', type=valid_file)