在代码中使用 alembic 命令后,如何阻止 alembic 记录器停用我自己的记录器?

问题描述 投票:0回答:2

我在代码中使用

alembic
在应用程序启动时应用数据库迁移。我还使用 Python 的内置
logging
lib 来登录终端。应用迁移后(或运行任何打印到
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.")

我可以做些什么来确保我的记录器正在记录?我想继续使用内置的日志记录功能,但我也愿意为此使用一些库。

python python-3.x logging alembic
2个回答
2
投票

答案将在您的

alembic.ini
文件中找到。

您正在运行一个旨在作为脚本而不是 API 调用的命令,因此 alembic 使用 logging.fileConfig

 
配置自己的日志记录,默认情况下使用
disable_existing_loggers=True
。该选项将禁用任何现有的非根记录器,除非它们或其祖先在日志记录配置文件中明确命名。

因此,阻力最小的方法就是在那里设置日志配置。

alembic.ini
中将有一个包含日志配置的部分 - 查找
[loggers]
部分标题。您需要修改内容,以便您自己的记录器保持可见 - 添加包含所需处理程序、格式化程序等的
[logger_app]
部分。

为了保持一致性,您可能也想从自己的脚本中切换到使用

fileConfig
,而不是
logging.basicConfig

另一种选择是在子进程中运行 alembic 脚本,这样它们的日志配置就不需要你关心了。子进程的 stdout/stderr 始终可以被捕获并作为主进程中的日志事件重新发送。


0
投票

虽然wim的答案引导我找到了解决方案,但我最终会为我实现的解决方案添加一个答案。采用这种方法,我不必在

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)

更改第四行以包含关键字参数

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)

logging docs提到此参数默认设置为

True
以实现向后兼容性:

警告

fileConfig()
函数采用默认参数
disable_existing_loggers
,出于向后兼容性的原因,默认为
True
。这可能是也可能不是您想要的,因为它会导致
fileConfig()
调用之前存在的任何非根记录器被禁用,除非它们(或祖先)在配置中明确命名。请参阅参考文档了解更多信息,如果您愿意,请为此参数指定
False

它没有提到这种兼容性到底是什么,并且我不确定我的应用程序是否使用 Python 3.12,是否需要它。

© www.soinside.com 2019 - 2024. All rights reserved.