Почему я получаю противоречивые исключения на Python? - PullRequest
3 голосов
/ 03 сентября 2010

Я столкнулся с очень странным поведением в Python, которое не согласовано.

...
except IOError as msg:
    sys.exit("###ERROR IOError: %s" % (msg))

Обычно это выдает мне сообщение вроде:

###ERROR IOError: [Errno 13] Permission denied: 'filename'

В тех же случаях приведенный выше код дает мне tuple вместо правильного сообщения об ошибке.

###ERROR IOError: (13, 'Permission denied')

Это очень странно, потому что во всех случаях исключения происходят из одного и того же метода python, codecs.open(...)

Что меня больше интересует, так это то, что если я уберу обработку, исключение достигнет верхних уровней с правильным текстом (полное сообщение об ошибке), всегда!

except IOError as msg:
    print(msg)
    raise msg

Приведенный выше пример будет всегда печатать полное сообщение, например IOError: [Errno 13] Permission denied: u'filename'.

Почему это происходит и как мне это предотвратить, я не хочу давать пользователям неполные сообщения об ошибках.

Я хотел воспроизвести это поведение в тестовом файле, но я не смог воспроизвести это за пределами проекта.

Я подозреваю, что это как-то связано с использованием sys.exit(), потому что print(msg) даст хороший результат, но sys.exit нет.

Ответы [ 3 ]

5 голосов
/ 03 сентября 2010

Во-первых, при вызове исключения, никогда до except Exc as e: raise e.Это всегда просто raise без аргументов.Это сохранит трассировку.

Нет, это не имеет ничего общего с sys.exit и не связано с тем, как было создано исключение.Вы всегда получаете исключение;просто иногда его строковое представление будет напоминать tuple.

>>> print IOError(13, 'Permission denied')
[Errno 13] Permission denied
>>> print IOError((13, 'Permission denied'))
(13, 'Permission denied')

Без полного отклика, невозможно определить, что именно вызывает ошибку таким образом.Кроме того, без надлежащего ререйзинга, как я указывал, вы не получите полный возврат.

1 голос
/ 03 сентября 2010

До Python 1.5 исключения были строками.После этого они изменили его на классы для обеспечения обратной совместимости.В настоящее время вы можете вызывать только экземпляры исключений или классы.

Я думаю, что был такой код:

error = (13, 'Permision denied')

#more code

raise error

После того, как они изменили его на исключение, кто-то просто сделал:

raise IOError(error)
0 голосов
/ 03 октября 2010

Я бы сказал, что вы не зависите от строкового представления исключения; Вы можете назвать это msg, но это ни строка, ни сообщение; это экземпляр исключения.

Так что вы можете создать свою собственную строку из кортежа msg.args и использовать ее в качестве «сообщения», которое вы хотите отобразить.

...