Сохранение сообщений об исключениях в Python
У меня возникла проблема с кодом на 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 ответ(ов)
Вам нужно определить, какой тип исключения вы хотите перехватить. Поэтому используйте 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))
Синтаксис больше не поддерживается в Python 3. Вместо этого используйте следующий код:
try:
do_something()
except BaseException as e:
logger.error('Не удалось выполнить действие: ' + str(e))
В некоторых случаях вы можете использовать атрибуты e.message или e.messages, но они не работают во всех случаях. В любом случае, более безопасно использовать str(e) для получения строкового представления исключения.
Пример кода:
try:
...
except Exception as e:
print(str(e))
Таким образом, вы всегда получите текстовое сообщение об ошибке, независимо от типа исключения.
Для более простого логирования в 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
обеспечивает более структурированный подход и позволяет вам легко управлять выводом и форматированием логов.
Используя 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)
Оба подхода позволят вам получить полную информацию о произошедшем исключении, включая стек вызовов, что значительно упростит процесс отладки.
Вручную вызов (бросание) исключения в Python
Поймать и вывести полный трейсбек исключения в Python без остановки/выхода из программы
Как напечатать исключение в Python?
Как проверить, существует ли переменная?
Как протестировать, что функция Python вызывает исключение?