9

Сохранение сообщений об исключениях в Python

6

У меня возникла проблема с кодом на Python, который я пишу для загрузки файлов на FTP-сервер. Вот фрагмент кода:

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')                 # файл для отправки
        con.storbinary('STOR ' + filepath, f)    # Отправить файл
        f.close()                                 # Закрыть файл и FTP-соединение
        logger.info('File successfully uploaded to ' + FTPADDR)
    except Exception as e:                        # Ошибка в этой строке
        logger.error('Failed to upload to ftp: ' + str(e))

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

5 ответ(ов)

12

Вам нужно определить, какой тип исключения вы хотите перехватить. Поэтому используйте except Exception as e: вместо except, e: для общего исключения.

Другой вариант — написать ваш код с блоками try/except следующим образом:

try:
    with open(filepath, 'rb') as f:
        con.storbinary('STOR ' + filepath, f)
    logger.info('Файл успешно загружен на ' + FTPADDR)
except Exception as e:      # работает в Python 3.x
    logger.error('Ошибка загрузки на FTP: %s', repr(e))

В более старых версиях Python 2.x используйте except Exception, e вместо except Exception as e:

try:
    with open(filepath, 'rb') as f:
        con.storbinary('STOR ' + filepath, f)
    logger.info('Файл успешно загружен на %s', FTPADDR)
except Exception, e:        # работает в Python 2.x
    logger.error('Ошибка загрузки на FTP: %s', repr(e))
3

Синтаксис больше не поддерживается в Python 3. Вместо этого используйте следующий код:

try:
    do_something()
except BaseException as e:
    logger.error('Не удалось выполнить действие: ' + str(e))
0

В некоторых случаях вы можете использовать атрибуты e.message или e.messages, но они не работают во всех случаях. В любом случае, более безопасно использовать str(e) для получения строкового представления исключения.

Пример кода:

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

Таким образом, вы всегда получите текстовое сообщение об ошибке, независимо от типа исключения.

0

Для более простого логирования в Python, который подходит как для версии 2, так и для 3, вы можете использовать следующий подход, не прибегая к модулю traceback. Это позволит вам обрабатывать исключения и регистрировать их в лог.

Вот пример кода:

import logging

logger = logging.Logger('catch_all')

def catchEverythingInLog():
    try:
        # ... выполняем некоторые операции ...
    except Exception as e:
        logger.error(e, exc_info=True)
        # ... обработка исключения ...

В данном случае мы создаем экземпляр Logger и используем logger.error() для записи ошибок. Параметр exc_info=True добавляет информацию о трассировке стека, что может быть полезно для дебага.

Сравните это с более старым способом, который все еще работает:

import sys

def catchEverything():
    try:
        # ... выполняем некоторые операции ...
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        # ... обработка исключения ...

Здесь exc_value содержит сообщение об ошибке, что позволяет вам обрабатывать исключения также эффективно, но использование logging обеспечивает более структурированный подход и позволяет вам легко управлять выводом и форматированием логов.

0

Используя str(e) или repr(e) для представления исключения, вы не получите фактический стек вызовов, поэтому это не поможет выяснить, где произошло исключение.

После изучения других ответов и документации по пакету логирования, я нашел два способа, которые отлично подходят для печати фактического стека вызовов, что упрощает отладку:

Используйте logger.debug() с параметром exc_info

try:
    # мой код
except SomeError as e:
    logger.debug(e, exc_info=True)

Используйте logger.exception()

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

try:
    # мой код
except SomeError as e:
    logger.exception(e)

Оба подхода позволят вам получить полную информацию о произошедшем исключении, включая стек вызовов, что значительно упростит процесс отладки.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь