обработка исключений для optparse из python - PullRequest
2 голосов
/ 25 октября 2010

Привет, ребята.

Я использую cmd и optparse для разработки CLI.py ​​для коллекции уже функциональных классов (CDContainer, CD и т. Д.).Ниже приведены некоторые части кода.У меня есть проблема здесь.когда есть исключения (неправильный тип ввода или пропущенные значения), 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)

В разделе "> python", если я наберу CLI.py, у меня будет (Cmd), поэтому я мог бы напечатать команду, например "(Cmd) addcd -t 3 -n thriller".но если я наберу "addcd -tr -n 3", то optparse прекратит работу всего CLI.py ​​и завершится.Это не хорошо для меня.Я хочу напомнить пользователю для каждого метода, а не завершать всю программу.

однако в документации optparse говорится, что «вся программа завершается».поэтому я не мог использовать optparse «вслепую».что я могу сделать?

Ответы [ 3 ]

10 голосов
/ 25 октября 2010

Документация optparse гласит:

Если поведение обработки ошибок по умолчанию в optparse не соответствует вашим потребностям, вам необходимо создать подкласс OptionParser и переопределить его методы exit () и / или error ().

В идеале вы должны определить новый тип исключения, подкласс 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 голосов
/ 07 апреля 2011
    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 перед попыткой - кроме блока toсправочная функция.

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

Спасибо за советы, кстати.

0 голосов
/ 25 октября 2010

Вероятно, это связано с типами, которые вы передаете классу CD: если вы его не увидите, есть очень хороший шанс, что он потерпит неудачу. Перед созданием этого объекта и передачей аргументов рекомендуется очистить эти данные, убедиться, что они правильного типа, и выполнить любые другие проверки, которые вы считаете разумными.

...