使用 alembic.config.main 重定向日志输出

Using alembic.config.main redirects log output

我有一个脚本可以执行数据库操作和 alembic API 调用以将新创建​​的数据库升级到 head。我在使用模块级记录器将日志写入文件的 python 记录器实例中遇到问题。

然后脚本调用 alembic.config.main(argv=alembic_args) 到 运行 迁移。但是,使用原始记录器实例的 alembic 调用后的每个日志语句都不会写入预期的日志文件。

这是一个重现该行为的示例脚本。

#!/usr/bin/env python3

import logging
import os

import alembic.config

from .utilities import get_migration_dir

logging.basicConfig(filename='test.log',
                    level=logging.DEBUG)

CUR_DIR = os.path.dirname(__file__)
LOG = logging.getLogger('so_log')

LOG.info('Some stuff')
LOG.info('More stuff')

alembic_config = (
    '--raiseerr',
    'upgrade', 'head'
)

os.chdir(get_migration_dir())

alembic.config.main(argv=alembic_config)

os.chdir(CUR_DIR)

LOG.debug('logging after alembic call.')
LOG.debug('more logging after alembic call.')
print('Code still running after alembic')

日志文件输出

INFO:so_log:Some stuff
INFO:so_log:More stuff

标准输出

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
print statement before alembic
Code still running after alembic

似乎记录器实例 LOG 在调用 alembic API 后正在丢失上下文或被定向到其他地方 API。

此外,我已经尝试 运行 在单独的线程中调用 alembic,结果相同。我期望发生的应该是日志语句在使用 alembic 进行迁移后继续写入指定的文件,但这并没有发生。而且,它实际上破坏了之后调用的任何代码的 LOG 实例;除非我在这里遗漏了什么。

这是因为 alembic 使用 alembic.ini 中的 fileConfig 设置日志记录,您可以在 env.py 脚本中看到它:

# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)

这有效地覆盖了您的原始记录器配置。

为避免这种情况,您可以简单地从 env.py 中删除此行,但是这将导致在从控制台 运行 宁 alembic 时不会生成任何日志。

一个更强大的选项是通过 alembic.command 而不是 alembic.config.main 运行 alembic 命令。这样您就可以在 运行 时间覆盖 alembic 配置:

from alembic.config import Config
import alembic.command

config = Config('alembic.ini')
config.attributes['configure_logger'] = False

alembic.command.upgrade(config, 'head')

然后在env.py:

if config.attributes.get('configure_logger', True):
    fileConfig(config.config_file_name)

我刚刚了解到 fileConfig 有一个关键字参数 disable_existing_loggers,默认为 True。只需将 disable_existing_loggers = False 添加到 env.py 中对 fileConfig 的调用 例如:

fileConfig(config.config_file_name, disable_existing_loggers=False)

似乎允许两种日志记录配置在不相互干扰的情况下工作(在某些情况下,这可能是首选,而不是必须选择另一个)

如果有人遇到这个问题,这里对我有用:

  • 正在更新 env.py 中的 fileConfig 调用: fileConfig(config.config_file_name, disable_existing_loggers = False)

  • alembic.ini[logger_root] 的级别更新到较低级别,因为它默认设置为 WARN