我正在使用一个基本的记录器来跟踪我的程序正在做什么的终端,我注意到日志有时会延迟几秒钟或几分钟,甚至无缘无故地被跳过。
这是我的日志记录设置:
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 动画,我怀疑它与这个问题有关,但我承认我不清楚为什么会出现这种情况以及如何出现这种情况。
有人经历过同样的事情吗?有没有办法“修复”它?
我有一个简单的 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.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。
这是日志记录模块中的错误,还是我在这里遗漏了一些东西?
我有一个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) 我正在开发一个包并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 记录器和 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 中记录异常的最正确方法是什么?
有些人只记录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) 这是我的日志配置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 查询是否记录到控制台?
我正在使用带有日志记录模块的Python,并且想将socket.hostname()添加到每条日志消息中,我必须在每条消息中运行此查询并且不能使用
name = socket.hostname()
Run Code Online (Sandbox Code Playgroud)
然后用名称记录格式
我正在研究这个使用日志过滤器的示例,但我这里需要的不是过滤器,而是对每个日志消息的简单操作。
我怎样才能达到想要的结果?
我正在尝试测试单元测试中是否记录了警告。看来以下测试应该失败:
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-logging ×10
logging ×7
python ×5
python-3.x ×5
django ×1
docker ×1
gitlab-ci ×1
pytest ×1
python-c-api ×1
ros ×1
rospy ×1
stdout ×1
subclass ×1