повідомлення про виключення python


520
import ftplib
import urllib2
import os
import logging
logger = logging.getLogger('ftpuploader')
hdlr = logging.FileHandler('ftplog.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)
FTPADDR = "some ftp address"

def upload_to_ftp(con, filepath):
    try:
        f = open(filepath,'rb')                # file to send
        con.storbinary('STOR '+ filepath, f)         # Send the file
        f.close()                                # Close file and FTP
        logger.info('File successfully uploaded to '+ FTPADDR)
    except, e:
        logger.error('Failed to upload to ftp: '+ str(e))

Це, здається, не працює, я отримую синтаксичну помилку. Який правильний спосіб зробити це для реєстрації різного роду винятків у файлі


2
Відступ порушено. І пропустіть ,після except.
Свен Марнах

3
@SvenMarnach, якщо пропустити ,після except, ви отримаєте global name 'e' is not defined, що не набагато краще, ніж неправильний синтаксис.
Вал

12
@Val: має бути except Exception as eабо except Exception, e, залежно від версії Python.
Свен Марнах

1
Напевно, це десь близько цих 8 відповідей, але коли ви відкриваєте файл, закрита частина ніколи не повинна знаходитися всередині оператора спробу, а або в остаточному операторі, або обгорненого з оператором.
JC Rocamonde

Відповіді:


733

Ви повинні визначити, який тип виключення ви хочете зловити. Тож пишіть except Exception, e:замість except, e:загального винятку (це все одно буде зареєстровано).

Інша можливість - написати цілий спробу / крім коду таким чином:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception, e: # work on python 2.x
    logger.error('Failed to upload to ftp: '+ str(e))

в Python 3.x та сучасних версіях Python 2.x використовують except Exception as eзамість except Exception, e:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception as e: # work on python 3.x
    logger.error('Failed to upload to ftp: '+ str(e))

118
repr (e) дає вам виняток (і рядок повідомлення); str (e) дає лише рядок повідомлення.
біла борода

11
В якості альтернативи для винятку ведення журналу ви можете скористатися logger.exception(e)натомість. Він буде записувати виняток із прослідковуванням на тому ж logging.ERRORрівні.
mbdevpl

1
@mbdevpl це здається неправдою. Схоже, дзвоніть str () за винятком: ideone.com/OaCOpO
KevinOrr

6
except Exception, e:кидає мені синтаксичну помилку в python 3. Це очікується?
Чарлі Паркер

27
@CharlieParker в Python3 пишутьexcept Exception as e:
eumiro

282

Синтаксис більше не підтримується в python 3. Використовуйте наведене нижче.

try:
    do_something()
except BaseException as e:
    logger.error('Failed to do something: ' + str(e))

2
Насправді, ви повинні використовувати logger.error ('Не вдалося щось зробити:% s', str (e)) Таким чином, якщо рівень вашого реєстратора вище помилки, він не робить інтерполяцію рядків.
avyfain

7
@avyfain - Ви неправі. Оператор logging.error('foo %s', str(e))завжди буде конвертувати eв рядок. Щоб досягти того, що ви хотіли б використати, logging.error('foo %s', e)тим самим дозволяючи рамці ведення журналу робити (або не робити) перетворення.
Рон Далгрен

1
Ви можете перевірити у відповіді на python REPL (тут із Python 3.5.2 та ipython): дивіться мою суть тут
Ron Dahlgren

2
В якості альтернативи для винятку ведення журналу ви можете скористатися logger.exception(e)натомість. Він буде записувати виняток із прослідковуванням на тому ж logging.ERRORрівні.
mbdevpl

11
Слідкуйте за тим except BaseExceptionі except Exceptionне на одному рівні. except Exceptionпрацює в Python3, але він не зачепить, KeyboardInterruptнаприклад (що може бути дуже зручно, якщо ви хочете перервати свій код!), тоді як BaseExceptionвилучає будь-яке виняток. Дивіться це посилання щодо ієрархії винятків.
jeannej

41

Оновлення цього до чогось більш простого для реєстратора (працює як для python 2, так і для 3). Вам не потрібен модуль відстеження.

import logging

logger = logging.Logger('catch_all')

def catchEverythingInLog():
    try:
        ... do something ...
    except Exception as e:
        logger.error(e, exc_info=True)
        ... exception handling ...

Це старий спосіб (хоча все ще працює):

import sys, traceback

def catchEverything():
    try:
        ... some operation(s) ...
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        ... exception handling ...

exc_value - повідомлення про помилку.


2
Це був би мій кращий метод. Я думаю, що друк рядка корисний для ведення журналів, але якщо мені потрібно щось робити з цією інформацією, мені потрібно більше, ніж просто рядок.
sulimmesh

3
Вам не потрібно "імпортувати прослідкування" у другому прикладі, правда?
starikoff

35

Є деякі випадки, коли ви можете використовувати e.message або e.messages .. Але це працює не у всіх випадках. У будь-якому випадку більш безпечним є використання str (e)

try:
  ...
except Exception as e:
  print(e.message)

42
Проблема з цим є, наприклад, якщо ви except Exception as e, і eце IOError, ви отримаєте e.errno, e.filenameі e.strerror, але , мабуть , немає e.message(принаймні , в Python 2.7.12). Якщо ви хочете записати повідомлення про помилку, використовуйте str(e), як в інших відповідях.
epalm

@epalm Що робити, якщо ви зловили IOError перед винятком?
Альберт Томпсон

@ HeribertoJuárez Навіщо ловити особливі випадки, тоді як ви можете просто кинути їх на рядок?
HosseyNJF

25

Якщо ви хочете клас помилки, повідомлення про помилку та трасування стека (або деякі з них), використовуйте sys.exec_info().

Мінімальний робочий код з деяким форматуванням:

import sys
import traceback

try:
    ans = 1/0
except BaseException as ex:
    # Get current system exception
    ex_type, ex_value, ex_traceback = sys.exc_info()

    # Extract unformatter stack traces as tuples
    trace_back = traceback.extract_tb(ex_traceback)

    # Format stacktrace
    stack_trace = list()

    for trace in trace_back:
        stack_trace.append("File : %s , Line : %d, Func.Name : %s, Message : %s" % (trace[0], trace[1], trace[2], trace[3]))

    print("Exception type : %s " % ex_type.__name__)
    print("Exception message : %s" %ex_value)
    print("Stack trace : %s" %stack_trace)

Що дає наступний вихід:

Exception type : ZeroDivisionError
Exception message : division by zero
Stack trace : ['File : .\\test.py , Line : 5, Func.Name : <module>, Message : ans = 1/0']

Функція sys.exc_info () дає детальну інформацію про останнє виключення. Він повертає кортеж (type, value, traceback).

tracebackє екземпляром об'єкта відстеження. Ви можете відформатувати трасування за допомогою наданих методів. Більше можна знайти в документації про відстеження .


3
Використання e.__class__.__name__ може також повернути клас виключень.
kenorb

19

Ви можете використовувати logger.exception("msg")для реєстрації виняток із відстеженням:

try:
    #your code
except Exception as e:
    logger.exception('Failed: ' + str(e))

Випадково e.msg- це рядкове представлення Exceptionкласу.
MarkHu

5
Або просто logger.exception(e).
mbdevpl


5

Ви можете спробувати точно вказати тип BaseException. Однак це дозволить спіймати лише похідні BaseException. Хоча це включає всі винятки, передбачені реалізацією, можливо також підняти довільні класи старого стилю.

try:
  do_something()
except BaseException, e:
  logger.error('Failed to do something: ' + str(e))


2

для майбутніх борців, у python 3.8.2 (і, можливо, кілька версій до цього), синтаксис є

except Attribute as e:
    print(e)

1

Використовуючи str(e)або repr(e)представляючи виняток, ви не отримаєте фактичного сліду стека, тому не корисно знайти де виняток.

Ознайомившись з іншими відповідями та документом пакета реєстрації документів, наступні два способи чудово спрацьовують для друку фактичного сліду стека для легшої налагодження:

використання logger.debug()з параметромexc_info

try:
    # my code
exception SomeError as e:
    logger.debug(e, exc_info=True)

використання logger.exception()

або ми можемо безпосередньо використовувати logger.exception()для друку винятку.

try:
    # my code
exception SomeError as e:
    logger.exception(e)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.