Использование alembic.config.main перенаправляет вывод журнала

У меня есть сценарий, который выполняет операции с базой данных вместе с вызовом API-интерфейса перегонного куба для обновления только что созданной базы данных до головы. У меня проблема с экземпляром регистратора python, когда журналы записываются в файл с использованием регистратора уровня модуля.

Затем сценарий вызывает alembic.config.main(argv=alembic_args) для выполнения миграции. Однако каждый оператор журнала после вызова перегонного куба, использующий исходный экземпляр средства ведения журнала, не записывается в ожидаемый файл журнала.

Вот пример сценария, который воспроизводит поведение.

#!/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 теряет контекст или перенаправляется в другое место после вызова API-интерфейса перегонного куба.

Кроме того, я попытался запустить вызов перегонного куба в отдельном потоке, который дал тот же результат. Я ожидаю, что операторы журнала продолжат запись в указанный файл после использования перегонного куба для миграции, но этого не происходит. И, кроме того, он фактически ломает экземпляр LOG для любого кода, который вызывается позже; Если я просто что-то пропустил здесь.


person trendsetter37    schedule 23.02.2017    source источник


Ответы (3)


Это связано с тем, что alembic настраивает ведение журнала с использованием fileConfig из alembic.ini, вы можете увидеть это в своем скрипте 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. Таким образом, вы можете переопределить конфигурацию перегонного куба во время выполнения:

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)
person aikoven    schedule 09.03.2017
comment
Ах я вижу. В итоге я запустил команду alembic в отдельном процессе во время выполнения. Ваше решение намного лучше. Спасибо. - person trendsetter37; 09.03.2017
comment
Это отличное решение. Я также хотел бы порекомендовать нам использовать экземпляр Config для установки нашего значения configure_logger вместо config.attributes. т.е. config = Config('alembic.ini', attributes={'configure_logger': False}) - person Imjohsep; 15.06.2017

Я только что узнал, что fileConfig принимает аргумент ключевого слова, disable_existing_loggers, который по умолчанию равен True. Просто добавьте disable_existing_loggers = False к вызову fileConfig в env.py, например:

fileConfig(config.config_file_name, disable_existing_loggers=False)

по-видимому, позволяет обеим конфигурациям ведения журнала работать, не мешая друг другу (что может быть предпочтительнее, чем в некоторых случаях выбирать один над другим)

person Styles    schedule 09.12.2019
comment
Это ДОЛЖЕН быть ответ. - person David Lin; 17.07.2020

Если кто-то столкнется с этой проблемой, вот что сработало для меня:

  • Обновление вызова fileConfig в env.py: fileConfig(config.config_file_name, disable_existing_loggers = False)

  • Обновление уровня для [logger_root] в alembic.ini на более низкий уровень, так как по умолчанию он установлен на WARN

person Sorix    schedule 17.02.2021