我想记录原始字节。但是,如果我将FileHandler中的文件模式从“ w”更改为“ wb”,则记录器将失败,并出现错误,无论我传递给它的是哪个数据:字符串还是字节。
logging.getLogger("clientIn").error(b"bacd")
Traceback (most recent call last):
File "/usr/lib/python3.4/logging/__init__.py", line 980, in emit
stream.write(msg)
TypeError: 'str' does not support the buffer interface
Call stack:
File "<string>", line 1, in <module>
File "/usr/lib/python3.4/multiprocessing/spawn.py", line 106, in spawn_main
exitcode = _main(fd)
File "/usr/lib/python3.4/multiprocessing/spawn.py", line 119, in _main
return self._bootstrap()
File "/usr/lib/python3.4/multiprocessing/process.py", line 254, in _bootstrap
self.run()
File "/usr/lib/python3.4/multiprocessing/process.py", line 93, in run
self._target(*self._args, **self._kwargs)
File "/home/serj/work/proxy_mult/proxy/connection_worker_process.py", line 70, in __call__
self._do_work(ipc_socket)
File "/home/serj/work/proxy_mult/proxy/connection_worker_process.py", line 76, in _do_work
logging.getLogger("clientIn").error("bacd")
Message: 'bacd'
Run Code Online (Sandbox Code Playgroud)
我需要使日志记录模块适应二进制数据的方法。
最简单的解决方案是将字节存储在字节串中。
另一种可能的方法是自定义您的日志记录。该文档是一个开始,但您需要查看人们如何完成此操作的示例。就我个人而言,我只使用了稍微定制的记录、处理程序和格式化程序来允许我的记录器使用 SQLite 后端。
有很多东西需要修改(很抱歉没有那么具体,但当涉及到 Python 的日志模块时,我仍然是一个初学者):
LogRecord- 如果您继承它,您将看到指定类型的__init__(...)参数。正如文档所述,事件描述消息可能是带有变量 data 占位符的格式字符串。恕我直言,如果应该只是一个字符串,那么它就不会是类型。这是一个您可以进一步调查的地方,包括。指某东西的用途。在许多情况下,继承并不是真正必要的,简单的继承就可以了。msgobjectmsgmsgobjectargsnamedtuple
LoggerAdapter- 有消息的上下文信息,其中可以包含任意数据(据我所知)。您将需要一个自定义适配器来使用它。
此外,您可能必须使用自定义Formatter和/或Handler. 最坏的情况是,您将不得不使用一些任意字符串消息,同时传递额外的数据(二进制或其他数据)。
这是一个快速而肮脏的示例,我使用 anamedtuple来保存额外的数据。请注意,我无法在没有实际消息的情况下传递额外数据,但如果您实现实际的自定义,则可能可以解决此问题LogRecord。另请注意,我省略了其余代码,因为这只是自定义演示:
TensorBoardLogRecord = namedtuple('TensorBoardLogRecord' , 'dtime lvl src msg tbdata')
TensorBoardLogRecordData = namedtuple('tbdata', 'image images scalar scalars custom_scalars')
class TensorBoardLoggerHandler(logging.Handler):
def __init__(self, level=logging.INFO, tboard_dir='./runs') -> None:
super().__init__(level)
self.tblogger = SummaryWriter(tboard_dir)
def emit(self, record: TensorBoardLogRecord) -> None:
# For debugging call print record.__dict__ to see how the record is structured
# If record contains Tensorboard data, add it to TB and flush
if hasattr(record, 'args'):
# TODO Do something with the arguments
...
class TensorBoardLogger(logging.Logger):
def __init__(self, name: str='TensorBoardLogger', level=logging.INFO, tboard_dir='./runs') -> None:
super().__init__(name, level)
self.handler = TensorBoardLoggerHandler(level, tboard_dir)
self.addHandler(self.handler)
...
logging.setLoggerClass(TensorBoardLogger)
logger = logging.getLogger('TensorBoardLogger')
logger.info('Some message', TensorBoardLogRecordData(None, None, 10000, None, None))
Run Code Online (Sandbox Code Playgroud)
我想做的是向记录器添加功能(仍在进行中),以实际编写 Tensorboard(在我的例子中来自 PyTorch 实用程序模块)日志条目,该日志条目可以通过网络浏览器内的工具进行可视化。你的不需要那么复杂。这个“解决方案”主要是为了防止您找不到覆盖msg处理的方法。
我还发现了这个存储库 -视觉日志记录,它使用loggingPython 模块的功能来处理图像。按照存储库提供的代码我能够得到
<LogRecord: TensorBoardLogger, 20, D:\Projects\remote-sensing-pipeline\log.py, 86, "TensorBoardLogRecord(image=None, images=None, scalar=1, scalars=None, custom_scalars=None)">
{'name': 'TensorBoardLogger', 'msg': TensorBoardLogRecord(image=None, images=None, scalar=1, scalars=None, custom_scalars=None), 'args': (), 'levelname': 'INFO', 'levelno': 20, 'pathname': 'D:\\Projects\\remote-sensing-pipeline\\log.py', 'filename': 'log.py', 'module': 'log', 'exc_info': None, 'exc_text': None, 'stack_info': None, 'lineno': 86, 'funcName': '<module>', 'created': 1645193616.9026344, 'msecs': 902.6343822479248, 'relativeCreated': 834.2068195343018, 'thread': 6508, 'threadName': 'MainThread', 'processName': 'MainProcess', 'process': 16208}
Run Code Online (Sandbox Code Playgroud)
只需致电
logger = TensorBoardLogger(tboard_dir='./LOG')
logger.info(TensorBoardLogRecord(image=None, images=None, scalar=1, scalars=None, custom_scalars=None))
Run Code Online (Sandbox Code Playgroud)
我变成TensorBoardLogRecord了哪里
TensorBoardLogRecord = namedtuple('TensorBoardLogRecord' , 'image images scalar scalars custom_scalars')
Run Code Online (Sandbox Code Playgroud)
正如您所看到的msgis my object TensorBoardLogRecord,它证实了我上面的声明以及文档中的声明 - 只要您正确自定义日志记录,您就可以记录您想要的任何内容。就存储库而言,我指出作者使用的是图像,它们是numpy对象。然而,最终这些图像是从图像文件中读取的,因此二进制数据也在那里。