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

tre*_*r37 8 python logging alembic python-3.5

我有一个脚本,它执行数据库操作以及一个alembic API调用,以将新创建​​的数据库升级为head.我遇到了一个python logger实例的问题,其中使用模块级记录器将日志写入文件.

然后脚本调用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')
Run Code Online (Sandbox Code Playgroud)

日志文件输出

INFO:so_log:Some stuff
INFO:so_log:More stuff
Run Code Online (Sandbox Code Playgroud)

标准输出

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
print statement before alembic
Code still running after alembic
Run Code Online (Sandbox Code Playgroud)

LOG在调用alembic API之后,似乎记录器实例正在丢失上下文或被指向其他地方.

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

aik*_*ven 10

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

# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)
Run Code Online (Sandbox Code Playgroud)

这有效地覆盖了原始记录器配置.

为避免这种情况,您只需删除此行env.py,但这将导致alembic从控制台运行时不生成任何日志.

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

from alembic.config import Config
import alembic.command

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

alembic.command.upgrade(config, 'head')
Run Code Online (Sandbox Code Playgroud)

然后在env.py:

if config.attributes.get('configure_logger', True):
    fileConfig(config.config_file_name)
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的解决方案。我还建议我们使用Config实例化来设置configure_logger值,而不是`config.attributes`。即。config = Config('alembic.ini',attribute = {'configure_logger':False})` (2认同)

小智 6

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

fileConfig(config.config_file_name, disable_existing_loggers=False)
Run Code Online (Sandbox Code Playgroud)

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

  • 这应该是答案。 (3认同)