标签: python-logging

如何使用 python 日志记录修复延迟输出?

我正在使用一个基本的记录器来跟踪我的程序正在做什么的终端,我注意到日志有时会延迟几秒钟或几分钟,甚至无缘无故地被跳过。

这是我的日志记录设置:

import logging
logging.basicConfig(
  level=logging.WARNING,
  format='%(asctime)s %(name)s %(levelname)s %(message)s'
)
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
Run Code Online (Sandbox Code Playgroud)

没什么特别的,这里是我使用记录器的代码示例,在按键事件之后,但在我决定处理事件之前发生了延迟:

    if event.key == "c":
        if self.mode != "clock":
            logger.info("switching to clock mode")
            self.mode = "clock"
            self.gravitons = []
            self.updateGravitonsKTree()
            self.canShuffle = False
    elif event.key == "f":
        if self.mode != "free":
            logger.info("switching to free mode")
            self.mode = "free"
            self.gravitons = []
            self.updateGravitonsKTree()
    (...)
Run Code Online (Sandbox Code Playgroud)

我确信只有记录器的输出被延迟或跳过,因为我可以看到程序的其余部分立即正常反应,所以我猜可能有一种缓冲区没有正确刷新,但我在日志记录模块的文档。

另外,在这个程序中,我使用了 matplotlib 动画,我怀疑它与这个问题有关,但我承认我不清楚为什么会出现这种情况以及如何出现这种情况。

有人经历过同样的事情吗?有没有办法“修复”它?

logging python-3.x python-logging

7
推荐指数
0
解决办法
1111
查看次数

C 扩展 - 如何将 printf 重定向到 python 记录器?

我有一个简单的 C 扩展(参见下面的示例),有时使用 printf 函数进行打印。我正在寻找一种方法来包装对 C 扩展中的函数的调用,以便所有这些 printfs 将被重定向到我的 python 记录器。

你好ç:

#include <Python.h>

static PyObject* hello(PyObject* self)
{
   printf("example print from a C code\n");
   return Py_BuildValue("");
}

static char helloworld_docs[] =
   "helloworld(): Any message you want to put here!!\n";

static PyMethodDef helloworld_funcs[] = {
   {"hello", (PyCFunction)hello,
   METH_NOARGS, helloworld_docs},
   {NULL}
};

static struct PyModuleDef cModPyDem =
{
    PyModuleDef_HEAD_INIT,
    "helloworld",
    "Extension module example!",
    -1,
    helloworld_funcs
};

PyMODINIT_FUNC PyInit_helloworld(void)
{
    return PyModule_Create(&cModPyDem);
};
Run Code Online (Sandbox Code Playgroud)

设置.py:

from distutils.core import setup, Extension
setup(name = 'helloworld', …
Run Code Online (Sandbox Code Playgroud)

logging stdout python-c-api python-3.x python-logging

7
推荐指数
1
解决办法
2601
查看次数

子类化logging.Formatter更改logging.Formatter的默认行为

我向记录器添加了两个具有不同格式化程序的处理程序。第一个需要子类化logging.Formatter来进行自定义格式化。默认格式化程序足以满足第二个处理程序的需要。

假设第一个格式化程序只是从消息中删除换行符。以下脚本说明了看似奇怪的行为:

import logging

logger = logging.getLogger(__name__)

class CustomFormatter(logging.Formatter):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    def format(self, record):
        record.msg = record.msg.strip().replace('\n', ' ')
        return super().format(record)

h1 = logging.StreamHandler()
formatter1 = CustomFormatter(fmt=None, datefmt=None)
h1.setFormatter(formatter1)
logger.addHandler(h1)

h2 = logging.StreamHandler()
formatter2 = logging.Formatter(fmt=None, datefmt=None)
h2.setFormatter(formatter2)
logger.addHandler(h2)

logger.warning('string with\nmultiple lines')
Run Code Online (Sandbox Code Playgroud)

输出如下:

string with multiple lines
string with multiple lines
Run Code Online (Sandbox Code Playgroud)

我期望的是这个:

string with multiple lines
string with 
multiple lines
Run Code Online (Sandbox Code Playgroud)

第二个格式化程序不应实现 的行为CustomFormatter,但它确实实现了。当我反转处理程序添加到记录器的顺序时,这种情况不会发生。

除非我误解了子类化,否则不应通过重写子类中的方法来更改基类的行为。当我重写除 之外的类的方法时,这似乎不是问题logging.Formatter

这是日志记录模块中的错误,还是我在这里遗漏了一些东西?

python logging subclass python-3.x python-logging

6
推荐指数
1
解决办法
2389
查看次数

为什么插值键“asctime”不是有效的选项名称?

我有一个setup.cfg

[tool:pytest]
doctest_encoding = utf-8
log_cli = 0
log_cli_level = INFO
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_cli_date_format=%Y-%m-%d %H:%M:%S
Run Code Online (Sandbox Code Playgroud)

我收到以下错误消息

$ pip install .[all]
Processing /some/repo
    ERROR: Complete output from command python setup.py egg_info:
    ERROR: Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-req-build-599014dc/setup.py", line 72, in <module>
        setup(**config)
      File "/usr/local/lib/python3.7/site-packages/setuptools/__init__.py", line 144, in setup
        _install_setup_requires(attrs)
      File "/usr/local/lib/python3.7/site-packages/setuptools/__init__.py", line 137, in _install_setup_requires
        dist.parse_config_files(ignore_option_errors=True)
      File "/usr/local/lib/python3.7/site-packages/setuptools/dist.py", line 695, in parse_config_files
        self._parse_config_files(filenames=filenames)
      File "/usr/local/lib/python3.7/site-packages/setuptools/dist.py", line 599, …
Run Code Online (Sandbox Code Playgroud)

pytest docker gitlab-ci python-logging

6
推荐指数
1
解决办法
3506
查看次数

如何对单个包使用 python 日志记录

我正在开发一个包并logging在开发过程中使用模块来记录我的调试/信息日志。有没有一种好方法可以只为我的包启用日志记录,而不为 root 以下的所有内容启用日志记录?

假设我有 my_package:

# Some package from elsewhere that I need but don't want to see logging from
import other_package  
    
import logging
from logging import NullHandler
logger = logging.getLogger(__name__)
logger.addHandler(NullHandler())

def my_func():
    logger.debug("a message")
Run Code Online (Sandbox Code Playgroud)

以及使用该包的主要函数:

import my_package
    
# Some package from elsewhere that I need but don't want to see logging from
import another_package

import logging
logging.basicConfig(level=logging.DEBUG)

my_package.my_func()
Run Code Online (Sandbox Code Playgroud)

此设置将让我看到my_func()对 的调用logger.debug(),但它也会显示logger.debug()来自 other_package 和 another_package 的任何调用,这是我不想看到的。如何设置只能看到 my_package 中的日志记录?

我可以做一些奇怪的事情,比如硬编码禁用彼此的包logging.propagate或类似的东西,但这感觉应该有更好的方法。

python logging python-logging

6
推荐指数
1
解决办法
1820
查看次数

ROS 记录器禁用 Python 记录器

我在使用 Python 记录器和 rospy 记录器时遇到问题。一开始,ROS 节点初始化后,Python 记录器就停止记录。我尝试通过向记录器添加流处理程序来解决该问题。现在,它仅记录 ROS 节点是否已初始化。

我在ROS git中读到了有关 rospy 和 python 日志记录冲突的信息,但似乎没有很好的解决方案可以专门使用 python 记录器,并且独立于 ROS 记录器来处理我的代码。

一些模块初始化记录器:

    path = "/some_directory/"
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    logger = logging.getLogger('logger_name')

    # logging file handler for basic log infos
    file_handler_info = logging.FileHandler('{}log.log'.format(path))
    file_handler_info.setFormatter(formatter)
    file_handler_info.setLevel(logging.INFO)
    logger.addHandler(file_handler_info)

    # logging file handler for critical warnings
    file_handler_critical = logging.FileHandler('{}critical.log'.format(path))
    file_handler_critical.setFormatter(formatter)
    file_handler_critical.setLevel(logging.WARNING)
    logger.addHandler(file_handler_critical)

    # logging stream handler for console output
    stream_handler = logging.StreamHandler()
    stream_handler.setFormatter(formatter)
    stream_handler.setLevel(logging.DEBUG)
    logger.addHandler(stream_handler)
Run Code Online (Sandbox Code Playgroud)

启动 ROS 节点的其他模块 …

python logging ros rospy python-logging

6
推荐指数
1
解决办法
1309
查看次数

在 python 中记录异常消息的正确方法

在 Python 中记录异常的最正确方法是什么?

有些人只记录e另一个日志属性e.message(但在某些例外情况下可能会丢失)。
一种用于str()捕获异常的描述,但它不包含错误类型,如果没有错误类型,有时就没用。
实际上repr()会返回错误类型和描述,但它并不那么流行(在我看到的项目中)。

还有一个相关问题:这如何影响像 Sentry 这样收集和分组错误/警报的服务。它们还应该包含一些有关具体错误的信息。

因此想再次开启这个讨论:哪种记录异常的方式最好使用?

def foo():
    """ Method that can raise various types of exceptions """
    1/0  # just for example

try:
    foo()
except Exception as e:
    logger.exception('Error occurred during execution: %s', e)          # 1
    logger.exception('Error occurred during execution: %s', e.message)  # 2
    logger.exception('Error occurred during execution: %s', str(e))     # 3
    logger.exception('Error occurred during execution: %s', str(e.message))  # 4
    logger.exception('Error occurred during execution: %s', repr(e))    # …
Run Code Online (Sandbox Code Playgroud)

python python-logging

6
推荐指数
1
解决办法
5252
查看次数

即使 DEBUG=False 也记录 SQL 查询

这是我的日志配置settings.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
        'file': {
            'class': 'logging.FileHandler',
            'filename': os.path.join(BASE_DIR, 'logs', 'django.log'),
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file', 'console'],
            'level': 'DEBUG',
        },
        'django.template': {
            'handlers': ['file', 'console'],
            'level': 'INFO',
        },
        'App': {
            'handlers': ['file', 'console'],
            'level': 'DEBUG',
        },
    },
}
Run Code Online (Sandbox Code Playgroud)

有一种我无法解释的行为:如果我运行,debug=True我可以看到所有 SQL 查询都记录到控制台,但是当debug=False这种情况没有发生时,即使我不更改上面的配置。

为什么是这样?如何在日志配置中确定 SQL 查询是否记录到控制台?

django logging python-logging

6
推荐指数
2
解决办法
3231
查看次数

在 Python 日志记录中向每条日志消息添加信息

我正在使用带有日志记录模块的Python,并且想将socket.hostname()添加到每条日志消息中,我必须在每条消息中运行此查询并且不能使用

name = socket.hostname() 
Run Code Online (Sandbox Code Playgroud)

然后用名称记录格式

我正在研究这个使用日志过滤器的示例,但我这里需要的不是过滤器,而是对每个日志消息的简单操作。

我怎样才能达到想要的结果?

python logging python-3.x python-logging

6
推荐指数
2
解决办法
4022
查看次数

任何级别的日志记录都可以让assertLogs 通过

我正在尝试测试单元测试中是否记录了警告。看来以下测试应该失败:

import logging
import unittest

LOG_FORMAT = '%(levelname)-10s %(asctime)s: %(message)s'


def set_up_logger(app_name, level=logging.INFO, file="test.log"):
    formatter = logging.Formatter(LOG_FORMAT)
    log = logging.getLogger(app_name)
    # The next line lets the test pass
    log.setLevel(level)
    return log

logger = set_up_logger(__name__)

class TestLogging(unittest.TestCase):
    def test_logging(self):
        with self.assertLogs(level=logging.WARNING):
            logger.info('foo')
Run Code Online (Sandbox Code Playgroud)

然而,它通过了 python 3.8.5。

如果我删除该log.setLevel(level)行,测试就会失败,正如预期的那样。如果我将该logger.info行替换为pass,那么测试也会按预期失败。

为什么在记录器上设置级别会让测试错误地通过?

python-3.x python-unittest python-logging

6
推荐指数
1
解决办法
926
查看次数