2010-10-25 116 views
2

嗨,夥計們。python optparse的異常處理

我正在使用cmd和optparse來爲已有功能的類(CDContainer,CD等)集合開發CLI.py。以下是代碼的一些部分。我在這裏遇到問題。當出現異常(錯誤的輸入類型或缺失值)時,optparse將退出整個程序而不是特定的命令方法。

import cmd 
class CLI(cmd.Cmd): 

    def do_addcd(self, line): 
     args=line.split() 
     parser = OptionParser() 
     parser.add_option("-t", "--track", dest="track_number", type="int", 
      help="track number") 
     parser.add_option("-n", "--cdname", dest="cd_name", type="string", 
      help="CD name") 
     (options, positional_args) = parser.parse_args(args[0:]) 
     cd_obj= CD() 
     cd_obj.addCD(options.track_number, options.cd_name) 

在 「>蟒」,如果I型CLI.py, 然後我將具有(CMD),所以可以輸入像命令 「(CMD)addcd -t 3 -n驚悚片」。 但如果我輸入「addcd -t r -n 3」,則optparse將終止整個CLI.py並退出。 這對我不好。我想提醒用戶每種方法,而不是終止整個程序。

但是,optparse文檔顯示「整個程序退出」。所以我不能「盲目」地使用optparse。我能做什麼?

回答

10

optparse文檔這樣說:

如果optparse的默認錯誤處理行爲不適合你的需求,你需要繼承OptionParser並覆蓋其出口()和/或錯誤()方法。

理想情況下,你會定義一個新的類型的異常,子類optparse的,提高在exit()error()方法,您已經覆蓋了異常,然後抓住它,並根據需要處理它。

雖然你可以作弊。如果您希望打印錯誤消息但不想讓程序退出,那麼您可以捕獲SystemExit異常,以捕獲optparse試圖退出並停止它的位置。

因此,舉例來說:

try:  
    (options, positional_args) = parser.parse_args(args[0:]) 
except SystemExit: 
    return 

cd_obj= CD() 
cd_obj.addCD(options.track_number, options.cd_name) 

或要覆蓋的方法:

import optparse 

class OptionParsingError(RuntimeError): 
    def __init__(self, msg): 
     self.msg = msg 

class OptionParsingExit(Exception): 
    def __init__(self, status, msg): 
     self.msg = msg 
     self.status = status 

class ModifiedOptionParser(optparse.OptionParser): 
    def error(self, msg): 
     raise OptionParsingError(msg) 

    def exit(self, status=0, msg=None): 
     raise OptionParsingExit(status, msg) 

然後:

try: 
    parser = ModifiedOptionParser() 
    parser.add_option("-t", "--track", dest="track_number", type="int", 
     help="track number") 
    (options, positional_args) = parser.parse_args(args[0:]) 
except OptionParsingError, e: 
    print 'There was a parsing error: %s' % e.msg 
    return 
except OptionParsingExit, e: 
    print 'The option parser exited with message %s and result code %s' % (e.msg, e.status) 
    return 

cd_obj= CD() 
cd_obj.addCD(options.track_number, options.cd_name) 
+0

我明白了。那麼我不使用optparse?我自己解析參數並相應地進行分析。如果我使用optparse,正如你所說的那樣,我應該以某種方式覆蓋它的退出或錯誤方法,但我並不確信我能做到。 – pepero 2010-10-25 12:20:49

+1

我會堅持optparse。它將保持選項解析行爲一致,並且編寫遵循常規約定的參數解析器將是很多工作。 我已經用覆蓋錯誤方法的示例更新了我的答案。 – 2010-10-25 12:39:50

+0

嗨,Robie,非常感謝你用代碼的詳細回答!它符合我的意圖!但只有一件事,當我調用method -help,例如addcd -h時,它會列出選項,然後退出程序。是否有可能解決它的「幫助」。非常感謝! – pepero 2010-10-25 13:03:10

0

它可能與你傳遞給CD類的類型有關:如果沒有看到它,它很有可能會失敗。在創建該對象並傳遞參數之前,清理這些數據,確保它是正確的類型並執行任何其他您認爲合理的檢查是非常好的主意。

0
try: 
    parser = ModifiedOptionParser() 
    parser.add_option("-t", "--track", dest="track_number", type="int", 
     help="track number") 
    (options, positional_args) = parser.parse_args(args[0:]) 
except OptionParsingError, e: 
    print 'There was a parsing error: %s' % e.msg 
    return 
except OptionParsingExit, e: 
    print 'The option parser exited with message %s and result code %s' % (e.msg, e.status) 
    return 

自定義異常類仍然不能處理顯示默認值的'-h --help'選項幫助上下文。

我做了什麼我嘗試之前使用sys.argv - 除了塊來處理幫助功能。

if sys.argv[1] == '-h' or sys.argv[1] == '--help': 
    raise Exception('help') 

parser = ModifiedOptionParser() 
... 
except Exception as value: 
    status = str(value) 
    if status is 'help': 
     parser.print_help() 
     return -1 # I need to set different return value 

感謝您的提示。