2009-08-04 77 views
4

我有一個應用程序允許您將事件數據發送到自定義腳本。您只需佈置命令行參數,並指定哪些事件數據與什麼參數一起使用。問題在於這裏沒有真正的靈活性。您繪製的每個選項都將被使用,但並非每個選項都必須有數據。因此,當應用程序建立要發送到腳本的字符串時,一些參數是空的,python的OptionParser錯誤與「錯誤:--someargument選項需要參數」解析Python中的空白選項

因爲有超過200點的數據,這不像我可以編寫單獨的腳本來處理每個可能參數的組合(這將需要2^200個腳本)。有沒有辦法在python的optionparser中處理空參數?

回答

8

對不起,我的第一個答案誤解了這個問題。在定義選項時,您可以完成將命令行標誌的可選參數使用回調操作類型的功能。使用下面的函數作爲回調(你可能會希望滿足你的需要),並將其配置爲每個標誌的,可以選擇性接收參數:

import optparse 

def optional_arg(arg_default): 
    def func(option,opt_str,value,parser): 
     if parser.rargs and not parser.rargs[0].startswith('-'): 
      val=parser.rargs[0] 
      parser.rargs.pop(0) 
     else: 
      val=arg_default 
     setattr(parser.values,option.dest,val) 
    return func 

def main(args): 
    parser=optparse.OptionParser() 
    parser.add_option('--foo',action='callback',callback=optional_arg('empty'),dest='foo') 
    parser.add_option('--file',action='store_true',default=False) 
    return parser.parse_args(args) 

if __name__=='__main__': 
    import sys 
    print main(sys.argv) 



從運行命令行你會看到:

# python parser.py 
(<Values at 0x8e42d8: {'foo': None, 'file': False}>, []) 

# python parser.py --foo 
(<Values at 0x8e42d8: {'foo': 'empty', 'file': False}>, []) 

# python parser.py --foo bar 
(<Values at 0x8e42d8: {'foo': 'bar', 'file': False}>, []) 
+0

這個變體的問題在於`--for = bar`將會不工作:`parser.py:error:--foo選項不會取值` – Tobias 2013-04-13 08:09:21

0

是的,有這樣做的,當你添加選項參數:

from optparse import OptionParser 
parser = OptionParser() 
parser.add_option("--SomeData",action="store", dest="TheData", default='') 

給這個默認參數值你想要的選項,它被指定,但有選擇地將參數。

+0

我使用的是默認選項,但只有在--SomeData未在命令行中指定時才使用。如果你這樣做:--SomeData --SomeMoreData等等,然後--SomeData錯誤,因爲它沒有傳遞一個值。 – directedition 2009-08-04 18:57:33

+0

@directctedition抱歉,我誤解了你的問題。用適合您的解決方案發布另一個答案。 – 2009-08-04 20:12:17

1

我不認爲optparse可以做到這一點。 argparse是一個不同的(非標準)模塊,可以在handle situations like this的選項中有可選值。

隨着optparse你必須要麼指定選項,包括它的價值或省略兩者。

0

Optparse已經允許你傳遞空字符串作爲選項參數。所以如果可能的話,將空字符串視爲「無值」。對於長選項,以下任何工作:

my_script --opt= --anotheroption 
my_script --opt='' --anotheroption 
my_script --opt="" --anotheroption 
my_script --opt '' --anotheroption 
my_script --opt "" --anotheroption 

對於短樣式選項,您可以使用的:

my_script -o '' --anotheroption 
my_script -o "" --anotheroption 

警告:這已經在Linux下測試,應該工作在相同其他Unixlike系統; Windows處理命令行引用的方式不同,可能不會接受上面列出的所有變體。

0

Mark Roddy的解決方案可以工作,但它需要在運行時修改解析器對象的屬性,並且不支持 - 或 - 以外的其他選項格式。 一個稍微沒有涉及的解決方案是在運行optparse之前修改sys.argv數組,並在不需要參數的交換機之後插入一個空字符串(「」)。 這個方法的唯一約束是你的選項默認爲一個可預測的值,而不是你插入到sys.argv中的那個(我選擇None作爲下面的例子,但它確實沒關係)。

以下代碼創建了一個示例解析器和一組選項,從解析器中提取允許的開關數組(使用一點實例變量magic),然後遍歷sys.argv,並且每次找到 允許切換,它會檢查它是否在沒有任何參數後給出。如果在切換後沒有參數,則將在命令行 上插入空字符串。修改sys.argv之後,調用解析器,並且可以檢查其值爲「」的選項,並相應地執行操作。

#Instantiate the parser, and add some options; set the options' default values to None, or something predictable that 
#can be checked later. 
PARSER_DEFAULTVAL = None 
parser = OptionParser(usage="%prog -[MODE] INPUT [options]") 
#This method doesn't work if interspersed switches and arguments are allowed. 
parser.allow_interspersed_args = False 
parser.add_option("-d", "--delete", action="store", type="string", dest="to_delete", default=PARSER_DEFAULTVAL) 
parser.add_option("-a", "--add", action="store", type="string", dest="to_add", default=PARSER_DEFAULTVAL) 

#Build a list of allowed switches, in this case ['-d', '--delete', '-a', '--add'] so that you can check if something 
#found on sys.argv is indeed a valid switch. This is trivial to make by hand in a short example, but if a program has 
#a lot of options, or if you want an idiot-proof way of getting all added options without modifying a list yourself, 
#this way is durable. If you are using OptionGroups, simply run the loop below with each group's option_list field. 
allowed_switches = [] 
for opt in parser.option_list: 
    #Add the short (-a) and long (--add) form of each switch to the list. 
    allowed_switches.extend(opt._short_opts + opt._long_opts) 

#Insert empty-string values into sys.argv whenever a switch without arguments is found. 
for a in range(len(sys.argv)): 
    arg = sys.argv[a] 
    #Check if the sys.argv value is a switch 
    if arg in allowed_switches: 
     #Check if it doesn't have an accompanying argument (i.e. if it is followed by another switch, or if it is last 
     #on the command line) 
     if a == len(sys.argv) - 1 or argv[a + 1] in allowed_switches: 
      sys.argv.insert(a + 1, "") 

options, args = parser.parse_args() 

#If the option is present (i.e. wasn't set to the default value) 
if not (options.to_delete == PARSER_DEFAULTVAL): 
    if options.droptables_ids_csv == "": 
     #The switch was not used with any arguments. 
     ... 
    else: 
     #The switch had arguments. 
     ... 
0

在檢查cp命令能夠理解例如--backup=simple--backup simple,我回答類似這樣的問題:

import sys 
from optparse import OptionParser 

def add_optval_option(pog, *args, **kwargs): 
    if 'empty' in kwargs: 
     empty_val = kwargs.pop('empty') 
     for i in range(1, len(sys.argv)): 
      a = sys.argv[i] 
      if a in args: 
       sys.argv.insert(i+1, empty_val) 
       break 
    pog.add_option(*args, **kwargs) 

def main(args): 
    parser = OptionParser() 
    add_optval_option(parser, 
         '--foo', '-f', 
         default='MISSING', 
         empty='EMPTY', 
         help='"EMPTY" if given without a value. Note: ' 
         '--foo=VALUE will work; --foo VALUE will *not*!') 
    o, a = parser.parse_args(args) 
    print 'Options:' 
    print ' --foo/-f:', o.foo 
    if a[1:]: 
     print 'Positional arguments:' 
     for arg in a[1:]: 
      print ' ', arg 
    else: 
     print 'No positional arguments' 

if __name__=='__main__': 
    import sys 
    main(sys.argv) 

自助廣告:這是opo模塊我thebops包的一部分... ;-)