Я использую alembic в своем коде, чтобы применять миграцию базы данных при запуске приложения. Я также использую встроенную библиотеку logging Python для входа в терминал. Однако после применения миграций (или запуска любой команды alembic, которая, кажется, печатает stdout) мои регистраторы перестают работать.
Код:
import logging
import alembic.command
from alembic.config import Config as AlembicConfig
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("app")
logger.debug("Applying alembic migrations.")
alembic_config = AlembicConfig("alembic.ini")
alembic_config.attributes["sqlalchemy.url"] = connection_string
alembic.command.upgrade(alembic_config, "head", tag = "from_app")
logger.debug("Terminating app.")
Ожидаемый результат:
DEBUG:app:Applying alembic migrations.
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
DEBUG:app:Terminating app.
Фактический результат:
DEBUG:app:Applying alembic migrations.
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
Последняя строка отсутствует.
Я попытался снова установить уровень журнала после применения миграции (я думал, что, возможно, это изменило уровень журнала корневого регистратора):
...
alembic.command.upgrade(alembic_config, "head", tag = "from_app")
logger.setLevel(logging.DEBUG)
logger.debug("Terminating app.")
Фактически даже logger.critical("blah") больше ничего не логирует.
Я также попробовал еще раз применить базовую конфигурацию и снова получить регистратор:
...
alembic.command.upgrade(alembic_config, "head", tag = "from_app")
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("app")
logger.debug("Terminating app.")
Но безрезультатно. Даже корневой регистратор больше не регистрирует:
...
alembic.command.upgrade(alembic_config, "head", tag = "from_app")
logging.basicConfig(level=logging.DEBUG)
logging.debug("Terminating app.")
Могу ли я что-нибудь сделать, чтобы убедиться, что мои регистраторы ведут журнал? Я хотел бы продолжать использовать встроенную функцию ведения журнала, но я также готов использовать для этого некоторую библиотеку.






Ответ найдётся в вашем alembic.ini файле.
Вы запускаете команду, которая должна была быть сценарием, а не вызовом API, поэтому перегонный куб настраивает собственное ведение журнала с помощью logging.fileConfig, который по умолчанию использует disable_existing_loggers=True. Эта опция отключит все существующие средства ведения журнала без полномочий root, если только они или их предки не указаны явно в файле конфигурации ведения журнала.
Таким образом, путь наименьшего сопротивления будет заключаться в настройке конфигурации ведения журнала там же. В alembic.ini будет раздел с настройкой ведения журнала — найдите заголовок [loggers] раздела. Вы захотите изменить содержимое так, чтобы ваши собственные регистраторы оставались видимыми — добавьте раздел [logger_app] с нужными обработчиками, форматтерами и т. д.
Ради последовательности вы также можете переключиться на использование fileConfig из вашего собственного скрипта вместо logging.basicConfig.
Альтернативным вариантом может быть запуск сценариев перегонного куба в подпроцессе, чтобы их конфигурация журналирования вас не касалась. Stdout/stderr подпроцесса всегда можно захватить и повторно отправить в виде событий журнала из вашего основного процесса.
Ах да, просто редактирование автоматически сгенерированного env.py тоже звучит разумно.
Хотя ответ Вима привел меня к решению, я добавлю ответ для решения, которое я реализовал в конце. При таком подходе мне не пришлось дублировать настройки логгера в alembic.ini, а необходимые изменения в коде были ограничены одной строкой.
env.py, созданный alembicВ env.py от alembic есть раздел, близкий к импорту, где настраиваются их логгеры:
# Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
fileConfig(config.config_file_name)
Изменение 4-й строки для включения параметра ключевого слова disable_existing_loggers=False позволит вашим собственным средствам ведения журнала продолжать работать и вести журнал:
# Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
fileConfig(config.config_file_name, disable_existing_loggers=False)
В документации по журналированию упоминается, что для этого параметра по умолчанию установлено значение True для обратной совместимости:
Предупреждение
Функция fileConfig() принимает параметр по умолчанию
disable_existing_loggers, который по умолчанию равенTrueиз соображений обратной совместимости. Это может быть, а может и не быть тем, что вы хотите, так как это приведет к отключению любых средств ведения журнала без полномочий root, существовавших до вызова fileConfig(), если они (или предок) не указаны явно в конфигурации. Для получения дополнительной информации обратитесь к справочной документации и при желании укажитеFalseдля этого параметра.
Там не упоминается, что именно представляет собой эта совместимость, и, используя Python 3.12 для своего приложения, я не уверен, нужна ли она мне вообще.
омг, огромное спасибо за этот указатель! Я попытался добавить свою конфигурацию в файл
alembic.ini. Но я хочу установить уровень ведения журнала во время выполнения, поэтому я также попробовал отредактироватьenv.pyалембика, где он создает свои регистраторы, и добавилdisable_existing_loggers=Falseк вызовуlogging.config.fileConfig. Теперь все работает как ожидалось!