English 中文(简体)
Python 日志记录器在调用从代码调用 Alembic 命令后不再伐木
原标题:Python logger not logging anymore after calling alembic command from code
I m using alembic in my code to apply database migrations at application start. I m also using Python s builtin logging lib to log to the terminal. After applying the migrations (or running any alembic command that prints to stdout it seems) my loggers stop working, though. Code: 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.") Expected output: DEBUG:app:Applying alembic migrations. INFO [alembic.runtime.migration] Context impl PostgresqlImpl. INFO [alembic.runtime.migration] Will assume transactional DDL. DEBUG:app:Terminating app. Actual output: DEBUG:app:Applying alembic migrations. INFO [alembic.runtime.migration] Context impl PostgresqlImpl. INFO [alembic.runtime.migration] Will assume transactional DDL. The last line is missing. I ve tried setting the log level again after applying the migrations (I thought maybe it changed the root logger log level): ... alembic.command.upgrade(alembic_config, "head", tag="from_app") logger.setLevel(logging.DEBUG) logger.debug("Terminating app.") In fact, even logger.critical("blah") won t log anything anymore. I ve also tried applying the basic config again and getting the logger again: ... alembic.command.upgrade(alembic_config, "head", tag="from_app") logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger("app") logger.debug("Terminating app.") But to no avail. Even the root logger isn t logging anymore: ... alembic.command.upgrade(alembic_config, "head", tag="from_app") logging.basicConfig(level=logging.DEBUG) logging.debug("Terminating app.") Is there anything I can do to make sure that my loggers are logging? I d like to keep using the builtin logging functionality, but I m also open to using some lib for that.
最佳回答
The answer will be found in your alembic.ini file. You re running a command which was intended to be a script, not an API call, so alembic is configuring its own logging using logging.fileConfig, which by default uses disable_existing_loggers=True. That option will disable any existing non-root loggers unless they or their ancestors are explicitly named in the logging configuration file. So, the path of least resistance will be to setup your logging configuration in there too. There will be a section with the logging configuration in alembic.ini - look for a [loggers] section header. You ll want to modify the content so that your own loggers remain visible - add a [logger_app] section with the desired handlers, formatters etc. For consistency s sake, you may want to switch to using fileConfig from your own script too, instead of the logging.basicConfig. An alternative option would be to run alembic scripts in a subprocess, so that their logging configuration doesn t concern you. The stdout/stderr of the subprocess can always be captured and re-emitted as log events from your main process.
问题回答
Although wim s answer led me to the solution, I ll add an answer for the solution I implemented in the end. Taking this approach, I didn t have to duplicate my logger settings in the alembic.ini and necessary changes to the code were limited to a single line. Edit the env.py generated by alembic In the env.py by alembic there s a section close to the imports, where their loggers get configurated: # 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) Changing the 4th line to include the keyword parameter disable_existing_loggers=False will allow your own loggers to keep running and logging: # 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) The logging docs mention that this parameter is set to True by default for backwards compatibility: Warning The fileConfig() function takes a default parameter, disable_existing_loggers, which defaults to True for reasons of backward compatibility. This may or may not be what you want, since it will cause any non-root loggers existing before the fileConfig() call to be disabled unless they (or an ancestor) are explicitly named in the configuration. Please refer to the reference documentation for more information, and specify False for this parameter if you wish. It doesn t mention what exactly constitutes this compatibility, and using Python 3.12 for my app I m not sure, if I even need it.




相关问题
Can Django models use MySQL functions?

Is there a way to force Django models to pass a field to a MySQL function every time the model data is read or loaded? To clarify what I mean in SQL, I want the Django model to produce something like ...

An enterprise scheduler for python (like quartz)

I am looking for an enterprise tasks scheduler for python, like quartz is for Java. Requirements: Persistent: if the process restarts or the machine restarts, then all the jobs must stay there and ...

How to remove unique, then duplicate dictionaries in a list?

Given the following list that contains some duplicate and some unique dictionaries, what is the best method to remove unique dictionaries first, then reduce the duplicate dictionaries to single ...

What is suggested seed value to use with random.seed()?

Simple enough question: I m using python random module to generate random integers. I want to know what is the suggested value to use with the random.seed() function? Currently I am letting this ...

How can I make the PyDev editor selectively ignore errors?

I m using PyDev under Eclipse to write some Jython code. I ve got numerous instances where I need to do something like this: import com.work.project.component.client.Interface.ISubInterface as ...

How do I profile `paster serve` s startup time?

Python s paster serve app.ini is taking longer than I would like to be ready for the first request. I know how to profile requests with middleware, but how do I profile the initialization time? I ...

Pragmatically adding give-aways/freebies to an online store

Our business currently has an online store and recently we ve been offering free specials to our customers. Right now, we simply display the special and give the buyer a notice stating we will add the ...

Converting Dictionary to List? [duplicate]

I m trying to convert a Python dictionary into a Python list, in order to perform some calculations. #My dictionary dict = {} dict[ Capital ]="London" dict[ Food ]="Fish&Chips" dict[ 2012 ]="...

热门标签