Python 在导入的库中记录全局变量

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

有人可以解释导入的库中记录行为的行为吗?该日志包含一个名为

trace_id
的所谓全局变量。

我有以下库:

my_library/
  __init__.py
  folder1/
    __init_.py
    helper.py

helper.py
看起来像:

import logging

logger = logging.getLogger(__name__)
def helper():
    logger.info('LOG IN HELPER')

我的主程序,导入这个库,看起来像这样:

import logging

trace_id = 1

class CustomLogger(logging.Logger):

    def _log(self, level, msg, args, exc_info=None, extra=None):
        extra = {'trace_id': trace_id}
        super(CustomLogger, self)._log(level, msg, args, exc_info, extra)


logger = logging.getLogger(__name__)

def config_logger():
    helper_logger = logging.getLogger("folder1")

    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(trace_id)s')

    handler = logging.StreamHandler()
    handler.setFormatter(formatter)
    handler.setLevel(logging.INFO)
    helper_logger.addHandler(handler)
    helper_logger.setLevel(logging.INFO)

def program():
    logger.info('main start')

    # <--- SET LOGGER CLASS FIRST ---> #
    logging.setLoggerClass(CustomLogger)
    from folder1.helper import helper

    config_logger()
    helper()
    global trace_id
    trace_id += 1
    helper()
    logging.setLoggerClass(logging.Logger)
    logger.info('main end')

我的

test_program.py
看起来像这样:

import logging
import program

logger = logging.getLogger(__name__)

class TestProgram:

    def test_helper(self):
        logger.info('LOG IN TEST')
        program.program()

这是我的问题。如果我首先设置记录器类

test_program
会以预期的输出运行:

-------------------------------- live log call ---------------------------------
INFO     test_program:test_program.py:9 LOG IN TEST
INFO     program:program.py:30 main start
2024-01-14 22:42:50,521 - folder1.helper - INFO - LOG IN HELPER - 1
INFO     folder1.helper:helper.py:5 LOG IN HELPER
2024-01-14 22:42:50,522 - folder1.helper - INFO - LOG IN HELPER - 2
INFO     folder1.helper:helper.py:5 LOG IN HELPER
INFO     program:program.py:40 main end

但是,如果我先import,如下图:

...
    logger.info('main start')

    # <--- IMPORT FIRST ---> #
    from folder1.helper import helper
    logging.setLoggerClass(CustomLogger)

    config_logger()
...

它给了我一个错误:

-------------------------------- live log call ---------------------------------
INFO     test_program:test_program.py:9 LOG IN TEST
INFO     program:program.py:30 main start
--- Logging error ---
Traceback (most recent call last):
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 435, in format
    return self._format(record)
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 431, in _format
    return self._fmt % record.__dict__
KeyError: 'trace_id'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 1084, in emit
    msg = self.format(record)
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 928, in format
    return fmt.format(record)
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 666, in format
    s = self.formatMessage(record)
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 635, in formatMessage
    return self._style.format(record)
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 437, in format
    raise ValueError('Formatting field not found in record: %s' % e)
ValueError: Formatting field not found in record: 'trace_id'
Call stack:
  File "/opt/bb/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/bb/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/opt/bb/lib/python3.8/site-packages/pytest/__main__.py", line 5, in <module>
    raise SystemExit(pytest.console_main())
  File "/opt/bb/lib/python3.8/site-packages/_pytest/config/__init__.py", line 192, in console_main
    code = main()
  File "/opt/bb/lib/python3.8/site-packages/_pytest/config/__init__.py", line 169, in main
    ret: Union[ExitCode, int] = config.hook.pytest_cmdline_main(
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/main.py", line 318, in pytest_cmdline_main
    return wrap_session(config, _main)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/main.py", line 271, in wrap_session
    session.exitstatus = doit(config, session) or 0
  File "/opt/bb/lib/python3.8/site-packages/_pytest/main.py", line 325, in _main
    config.hook.pytest_runtestloop(session=session)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/main.py", line 350, in pytest_runtestloop
    item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 114, in pytest_runtest_protocol
    runtestprotocol(item, nextitem=nextitem)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 133, in runtestprotocol
    reports.append(call_and_report(item, "call", log))
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 222, in call_and_report
    call = call_runtest_hook(item, when, **kwds)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 261, in call_runtest_hook
    return CallInfo.from_call(
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 341, in from_call
    result: Optional[TResult] = func()
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 262, in <lambda>
    lambda: ihook(item=item, **kwds), when=when, reraise=reraise
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 169, in pytest_runtest_call
    item.runtest()
  File "/opt/bb/lib/python3.8/site-packages/_pytest/python.py", line 1792, in runtest
    self.ihook.pytest_pyfunc_call(pyfuncitem=self)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/python.py", line 194, in pytest_pyfunc_call
    result = testfunction(**testargs)
  File "/mnt/c/playground/tests/test_program.py", line 10, in test_helper
    program.program()
  File "/mnt/c/playground/program.py", line 35, in program
    helper()
  File "/mnt/c/my_library/folder1/helper.py", line 5, in helper
    logger.info('LOG IN HELPER')
Message: 'LOG IN HELPER'
Arguments: ()
self_logger class is <class 'logging.Logger'>
INFO     folder1.helper:helper.py:5 LOG IN HELPER
--- Logging error ---
Traceback (most recent call last):
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 435, in format
    return self._format(record)
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 431, in _format
    return self._fmt % record.__dict__
KeyError: 'trace_id'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 1084, in emit
    msg = self.format(record)
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 928, in format
    return fmt.format(record)
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 666, in format
    s = self.formatMessage(record)
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 635, in formatMessage
    return self._style.format(record)
  File "/opt/bb/lib/python3.8/logging/__init__.py", line 437, in format
    raise ValueError('Formatting field not found in record: %s' % e)
ValueError: Formatting field not found in record: 'trace_id'
Call stack:
  File "/opt/bb/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/bb/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/opt/bb/lib/python3.8/site-packages/pytest/__main__.py", line 5, in <module>
    raise SystemExit(pytest.console_main())
  File "/opt/bb/lib/python3.8/site-packages/_pytest/config/__init__.py", line 192, in console_main
    code = main()
  File "/opt/bb/lib/python3.8/site-packages/_pytest/config/__init__.py", line 169, in main
    ret: Union[ExitCode, int] = config.hook.pytest_cmdline_main(
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/main.py", line 318, in pytest_cmdline_main
    return wrap_session(config, _main)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/main.py", line 271, in wrap_session
    session.exitstatus = doit(config, session) or 0
  File "/opt/bb/lib/python3.8/site-packages/_pytest/main.py", line 325, in _main
    config.hook.pytest_runtestloop(session=session)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/main.py", line 350, in pytest_runtestloop
    item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 114, in pytest_runtest_protocol
    runtestprotocol(item, nextitem=nextitem)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 133, in runtestprotocol
    reports.append(call_and_report(item, "call", log))
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 222, in call_and_report
    call = call_runtest_hook(item, when, **kwds)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 261, in call_runtest_hook
    return CallInfo.from_call(
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 341, in from_call
    result: Optional[TResult] = func()
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 262, in <lambda>
    lambda: ihook(item=item, **kwds), when=when, reraise=reraise
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/runner.py", line 169, in pytest_runtest_call
    item.runtest()
  File "/opt/bb/lib/python3.8/site-packages/_pytest/python.py", line 1792, in runtest
    self.ihook.pytest_pyfunc_call(pyfuncitem=self)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/opt/bb/lib/python3.8/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
  File "/opt/bb/lib/python3.8/site-packages/_pytest/python.py", line 194, in pytest_pyfunc_call
    result = testfunction(**testargs)
  File "/mnt/c/playground/tests/test_program.py", line 10, in test_helper
    program.program()
  File "/mnt/c/playground/program.py", line 38, in program
    helper()
  File "/mnt/c/my_library/folder1/helper.py", line 5, in helper
    logger.info('LOG IN HELPER')
Message: 'LOG IN HELPER'
Arguments: ()
INFO     folder1.helper:helper.py:5 LOG IN HELPER
INFO     program:program.py:40 main end

我不确定我的知识差距是否在于Python日志模块、Python全局变量、导入库,还是以上所有。任何帮助将不胜感激。

python logging import global
1个回答
0
投票

setLoggerClass
设置未来
getLogger
调用使用的类。如果在设置自定义类之前导入
helper.py
,则其模块级别
getLogger
会获取默认的
Logger
类,而不是
CustomLogger
,因此没有
trace_id
。您的格式化程序假设
trace_id
存在,并且对于设置自定义类之前获取的记录器将失败。

显而易见的解决方案是确保您的脚本在导入之前设置其自定义记录器,就像您的第一个示例一样。但这并没有涵盖所有基础。假设其他代码决定需要不同的记录器并直接实例化它。

另一个解决方案是在创建格式化程序时添加默认值

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(trace_id)s', 
    defaults={"trace_id":trace_id}) 

如果您想要更多地控制输出,您可以创建自己的自定义格式化程序。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.