Скрипты Python – это клей, который удерживает многие приложения и их инфраструктура работает, но когда один из ваших скриптов выдает исключение вы можете не узнать об этом сразу, если у вас нет централизованного места для агрегировать ошибки. Вот где добавление Sentry может решить эту проблему с распределенной регистрацией ошибок.
В этом руководстве мы увидим, как быстро добавить Sentry в новый или существующий Скрипт Python для централизованного сообщения об ошибках для дальнейшего отладка.
Настройка среды разработки
Убедитесь, что у вас установлен Python 3. На данный момент Python 3.8.3 – последняя версия версия Python.
В этом уроке мы также будем использовать:
- размещенный экземпляр Sentry на sentry.io , который мы
- нужна учетная запись для доступа
- вспомогательную библиотеку Sentry Python для
- отправить данные об исключении в наш экземпляр Sentry
Установите вышеуказанные библиотеки кода в новый Виртуальная среда Python используя следующие команды:
python -m venv sentryscript source sentryscript/bin/activate pip install sentry-sdk>=0.14.4
Наша среда разработки сейчас готов, и мы можем написать код, который будет генерировать исключения для демонстрации как использовать Sentry.
Обратите внимание, что весь код этого руководства можно найти в примеры-кода-блога Репозиторий Git на GitHub под python-script-sentry каталог.
Пример сценария для загрузки модулей Python
Мы начнем с написания небольшого, но полезного скрипта, который распечатывает имена всех модулей в пакете Python, затем добавьте к нему Sentry когда становится очевидным, что захват исключений будет полезное дополнение.
Создайте новый файл с именем module_loader.py
и напишите следующие строки кода в нем, чтобы мы могли легко его выполнить в командной строке.
import argparse def import_submodules(package): return {} if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("package") args = parser.parse_args() package_to_load = args.package results = import_submodules(package_to_load) for r in results: print(str(r))
Приведенный выше код принимает аргумент, когда скрипт вызывается из командная строка и использует значение как ввод в заглушку import_submodules
, которая будет содержать код для обхода дерево модулей внутри пакета.
Затем добавьте следующие выделенные строки кода, чтобы использовать importlib
и pkgutil
для рекурсивного импорта модулей из пакета, если он найдено, что соответствует имени, переданному в качестве аргумента package
.
import argparse import importlib import pkgutil def import_submodules(package): """Import all submodules of a module, recursively, including subpackages. :param package: package (name or actual module) :type package: str | module :rtype: dict[str, types.ModuleType] """ if isinstance(package, str): package = importlib.import_module(package) results = {} for loader, name, is_pkg in pkgutil.walk_packages(package.__path__): full_name = package.__name__ + '.' + name try: results[full_name] = importlib.import_module(full_name) if is_pkg: results.update(import_submodules(full_name)) except ModuleNotFoundError as mnfe: print("module not found: {}".format(full_name)) except Exception as general_exception: print(general_exception) return results if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("package") args = parser.parse_args() package_to_load = args.package results = import_submodules(package_to_load) for r in results: print(str(r))
Новый код выше проходит через все пакеты с walk_package
в стандартной библиотеке pkgutil
модуль и пытается импортировать его с помощью import_module
на имя пакета плюс пакет в виде строки. Если результат успешен, функция будет рекурсивно вызывать сам для импорта подмодулей в импортированный пакет. Если модуль не найден или возникает другая проблема, исключения пойманы так, чтобы сценарий не отказал, а вместо этого мог продолжить обработку потенциальных модулей.
Протестируйте полный сценарий, чтобы увидеть, что он распечатывает с произвольным пакет в командной строке:
python module_loader.py importlib
В приведенном выше примере создается вывод:
importlib._bootstrap importlib._bootstrap_external importlib.abc importlib.machinery importlib.resources importlib.util
Попытка проверить пакет, который не установлен, приведет к ошибке. Использовать сценарий с пакетом, который не установлен в вашей текущей среде.
python module_loader.py flask
Вышеупомянутая команда производит следующую трассировку из-за ожидаемого ModuleNotFoundError
.
Traceback (most recent call last): File "module_loader.py", line 35, inresults = import_submodules(package_to_load) File "module_loader.py", line 14, in import_submodules package = importlib.import_module(package) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File " ", line 1006, in _gcd_import File " ", line 983, in _find_and_load File " ", line 965, in _find_and_load_unlocked ModuleNotFoundError: No module named 'flask'
Если вы установите Flask в свою текущую среду, модуль будет найден и приложение пройдется по списку модулей и подмодулей.
Наш пример скрипта можно использовать, но что, если мы запустим этот код или что-то подобное на одном или нескольких серверах, которые мы не так часто проверяем? Вот где это будет быть полезным, чтобы иметь способ объединить вывод исключения одного или нескольких сценариев в одном месте. Sentry может помочь нам в достижении этой цели.
Добавление отчетов об исключениях с помощью Sentry
Sentry может быть самостоятельно размещенным или используется в качестве облачной службы через Sentry.io . В этом мы будем использовать облачную версию, потому что она быстрее, чем настройка собственного сервера, а также бесплатно для небольших проектов.
Перейдите на главную страницу Sentry.io .
Войдите в свою учетную запись или зарегистрируйте новую бесплатную учетную запись. Вы будете в главная панель управления учетной записью после входа в систему или завершения знака Sentry вверх процесс.
На нашей панели управления учетной записью пока нет ошибок, как ожидается, потому что мы еще не подключили нашу учетную запись к Python сценарий.
Вы захотите создать новый проект Sentry Project только для этого приложения, чтобы нажмите «Проекты» на левой боковой панели, чтобы перейти на страницу «Проекты».
На странице “Проекты” нажмите кнопку “Создать проект” в правом верхнем углу. угол страницы.
Выберите Python, дайте вашему новому проекту имя и нажмите «Создать проект». кнопка. Наш новый проект готов к интеграции с нашим скриптом Python.
Нам нужен уникальный идентификатор для нашей учетной записи и проекта для авторизации нашего Код Python для отправки ошибок этому экземпляру Sentry. Самый простой способ получить нам нужно пойти в страница документации по началу работы с Python и прокрутите вниз до раздела «Настроить SDK».
Скопируйте строковый параметр для метода init
и установить его как переменную среды вместо того, чтобы выставлять его прямо в коде вашего приложения.
export SENTRY_DSN='https://yourkeygoeshere.ingest.sentry.io/project-number'
Обязательно замените yourkeygoeshere своим уникальным идентификатором и “номер проекта” с идентификатором, который соответствует проекту, который вы только что создан.
Убедитесь, что SENTRY_DSN
правильно установлен в вашей оболочке, используя echo
команда:
echo $SENTRY_DSN
Измените приложение для отправки информации об исключении в Sentry прямо сейчас что у нас есть уникальный идентификатор. Снова откройте module_loader.py
и обновите следующие выделенные строки кода.
import argparse import importlib import os import pkgutil import sentry_sdk from sentry_sdk import capture_exception # find on https://docs.sentry.io/error-reporting/quickstart/?platform=python sentry_sdk.init(dsn=os.getenv('SENTRY_DSN')) def import_submodules(package): """Import all submodules of a module, recursively, including subpackages. :param package: package (name or actual module) :type package: str | module :rtype: dict[str, types.ModuleType] """ if isinstance(package, str): package = importlib.import_module(package) results = {} for loader, name, is_pkg in pkgutil.walk_packages(package.__path__): full_name = package.__name__ + '.' + name try: results[full_name] = importlib.import_module(full_name) if is_pkg: results.update(import_submodules(full_name)) except ModuleNotFoundError as mnfe: print("module not found: {}".format(full_name)) capture_exception(mnfe) except Exception as general_exception: print(general_exception) capture_exception(general_exception) return results if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("package") args = parser.parse_args() package_to_load = args.package results = import_submodules(package_to_load) for r in results: print(str(r))
Эти новые строки кода импортируют Sentry Python SDK и os
библиотека (для чтения системных переменных окружения). Затем приложение инициализирует Sentry SDK строкой из SENTRY_DSN
переменная окружения. В функции import_submodules
мы затем вызовите функцию SDK capture_exception
всякий раз, когда Возникает ModuleNotFoundException
или другое исключение, которое попадать в более широкий сегмент Exception
.
Теперь, когда наш код готов, давайте протестируем новую интеграцию с Sentry.
Тестирование скрипта и просмотр исключений
Самый простой способ проверить, работает ли код Sentry или нет, – это чтобы попытаться импортировать несуществующий модуль. Допустим, вы делаете опечатку в вашей команде и попробуйте вместо этого запустить сценарий на importliba
из importlib
(может быть, потому что вы используете ужасную “бабочку” Macbook Pro клавиатура вместо прочной). Попробуйте и посмотрите, что произойдет:
python module_loader.py importliba
Скрипт запустится и завершится, но будут ошибки, потому что модуль не существует. Благодаря нашему новому коду мы можем просматривать ошибки в Sentry.
Проверьте панель управления Sentry, чтобы увидеть ошибку.
Мы также можем нажать на ошибку, чтобы узнать больше о том, что произошло.
Вы также можете получать отчеты об ошибках по электронной почте, чтобы вам не обязательно всегда оставаться в личном кабинете.
Когда все это настроено, у нас теперь есть отличная база для расширения скрипта. и улучшите обработку ошибок с помощью Sentry в качестве нашего приложения Python становится более сложным.
Что дальше?
Мы только что создали пример сценария, который выводит все модули и подмодули в пакете, а затем добавил в него Sentry, чтобы он сообщал любые исключения назад к нашему центральному размещенному экземпляру.
Это просто введение в Sentry, так что теперь вам нужно прочтите одну из следующих статей, чтобы узнать о нем больше:
Вы также можете получить представление о том, что кодировать дальше в своем проекте Python, чтение Страница полного содержания Python.
Вопросов? Свяжитесь со мной через Twitter @fullstackpython или @mattmakai . Я также на GitHub с имя пользователя mattmakai .
Что-то не так с этим сообщением? Вилка исходный код этой страницы на GitHub и отправьте запрос на перенос.