2013-03-04 115 views
2

可以使用​​来验证文件名cmd行参数的文件扩展名吗?python argparse文件扩展名检查

例如如果我有一个python脚本,我从CMD线运行:

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

我想argparse接受一日2个CMD行选项,但拒绝第三

我知道你可以做这样的事情:

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

指定的CMD线选择两个有效的选择

什么,我想是这样的:

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

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

回答

7

当然 - 你只需要指定一个适当的功能作为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() 

这里的缺点是,代码越来越多一点在某些方面复杂 - 结果是,当你真正去格式化你的参数时,界面变得更清洁一点。

+0

ummmm .... notcsv输入名称不正确?这也取决于'解析器'作为一个全球性的,而我认为提出异常是正确的方式... – 2013-03-04 14:37:54

+0

我想到了这一点...但我想保持简单的例子...我想你可以做'file_choices (('.csv','.tab))'这很好。或者你可以改变检查到'如果不是在选择'ext'是'os.path.splitext(fname)[1]'或其他任何东西...... – mgilson 2013-03-04 14:39:53

+0

Jon Clements和mgilson的答案现在看起来类似 - 有没有在这里使用lambda的好处是什么? - 它看起来似乎比Jon – bph 2013-03-04 14:48:24

-1

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

你可以随时检查它自己,并提供反馈给用户,虽然。

4

定义自定义函数,该函数的名称作为字符串 - 分割拓客进行比较,只是返回一个字符串,如果它的好,否则提高该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) 
+0

所以你可以在parser.parse_args()之前调用valid_file? – bph 2013-03-04 14:42:59

+0

@Hiett nope,你指定它为'add_argument'类型,如上所示... – 2013-03-04 14:44:25