python - Python 中的线程安全警告

标签 python logging python-3.x warnings

我正在尝试找到一种记录警告消息的好方法,但要在其中附加只有函数调用者知道的信息。

我想举个例子就很清楚了。

# log method as parameter

class Runner1(object):

    def __init__(self, log):
        self.log = log

    def run(self):
        self.log('First Warning')
        self.log('Second Warning')
        return 42


class Main1(object):

    def __init__(self):
        self._runner = Runner1(self.log)

    def log(self, message):
        print('Some object specific info: {}'.format(message))

    def run(self):
        print(self._runner.run())

e1 = Main1()
e1.run()

Main 对象有一个日志功能,可以在记录之前向任何消息添加自己的信息。此日志函数作为参数提供(在本例中为 Runner 对象)。一直携带这个额外的参数非常烦人,我想避免它。通常有很多对象/函数,因此我放弃了使用日志记录方法,因为我需要为每个对象创建不同的记录器。 (这是正确的吗?)

我尝试使用警告模块冒泡警告:

# warning module

import warnings

class Runner2(object):

    def run(self):
        warnings.warn('First Warning')
        warnings.warn('Second Warning')
        return 42


class Main2(object):

    def __init__(self):
        self._runner = Runner2()

    def log(self, message):
        print('Some object specific info: {}'.format(message))

    def run(self):
        with warnings.catch_warnings(record=True) as ws:
            warnings.simplefilter("always")
            out = self._runner.run()
            for w in ws:
                self.log(w.message)
        print(out)

e2 = Main2()
e2.run()

但是根据文档,这不是线程安全的。

最后,我也尝试了一些生成器:

# yield warning

class _Warning(object):

    def __init__(self, message):
        self.message = message


class Runner3(object):

    def run(self):
        yield _Warning('First Warning')
        yield _Warning('Second Warning')
        yield 42


class Main3(object):

    def __init__(self):
        self._runner = Runner3()

    def log(self, message):
        print('Some object specific info: {}'.format(message))

    def run(self):
        for out in self._runner.run():
            if not isinstance(out, _Warning):
                break
            self.log(out.message)
        print(out)


e3 = Main3()
e3.run()

但是您必须修改 Runner.run 以产生(而不是返回)最终结果这一事实很不方便,因为必须专门更改函数才能以这种方式使用(也许将来会改变? PEP255 中的最后一次质量检查)。另外,我不确定这种实现方式是否还有其他问题。

所以我要寻找的是一种不需要传递参数的线程安全的冒泡警告方式。我也希望没有警告的方法保持不变。添加一个特殊的构造,例如 yield 或 warning.warn 来冒泡警告就可以了。

有什么想法吗?

最佳答案

import Queue

log = Queue.Queue()
class Runner1(object):

    def run(self):
        log.put('First Warning')
        log.put('Second Warning')
        return 42

class Main1(object):

    def __init__(self):
        self._runner = Runner1()

    def log(self, message):
        print('Some object specific info: {0}'.format(message))

    def run(self):
        out=self._runner.run()
        while True:
            try:
                msg = log.get_nowait()
                self.log(msg)
            except Queue.Empty:
                break
        print(out)


e1 = Main1()
e1.run()

产量

Some object specific info: First Warning
Some object specific info: Second Warning
42

关于python - Python 中的线程安全警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7264002/

相关文章:

Python端口转发/多路复用服务器

Python virtualenv 选择了错误的库

python - 在Python中使用curses进行日志记录

python - 消除数据框中的重复行并保留具有特定字符串值的行

python - 相当于Python中的pySpark flatMap

python - 需要找到有效的方法来找到强数

python - 根据 bool 列过滤 pandas 数据框行

java - 如何将 javax 记录器句柄设置为重构敏感

java - Log4J fileappender 无法在 Websphere 7 上滚动

python - 尝试清理安装 python (anaconda),出现与先前安装相关的错误