2013-03-04 93 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