Python中的线程安全警告 [英] Thread-safe warnings in Python

查看:87
本文介绍了Python中的线程安全警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到一种记录警告消息的好方法,但是将仅由函数调用者知道的信息附加到该消息上.

I am trying to find a good way to log a warning message but appending to it information that is only known by the caller of the function.

我想举一个例子很清楚.

I think it will be clear with an example.

# 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对象)给出.始终携带此额外参数非常烦人,我想避免使用它.通常有很多对象/功能,因此我已经放弃使用日志记录方法,因为我需要为每个对象创建一个不同的记录器. (这正确吗?)

The Main object has a log function that adds to any message its own information before logging it. This log function is given as a parameter (in this case to a Runner object). Carrying this extra parameter all the time is extremely annoying and I would like to avoid it. There are usually lots of object/functions and therefore I have discarded the use of the logging method as I would need to create a different logger for each object. (Is this correct?)

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

I have tried to bubble the warning using the warning module:

# 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()

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

But according to the docs, this is not thread safe.

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

Finally, I have also tried some generators:

# 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 )中的最后一次质量检查.此外,我不确定这种实施方式是否还会遇到其他麻烦.

But the fact that you have to modify the Runner.run to yield (instead of return) the final result is inconvenient as functions will have to be specifically changed to be used in this way (Maybe this will change in the future? Last QA in PEP255). Additionally, I am not sure if there is any other trouble with this type of implementation.

因此,我正在寻找的是一种无需发出参数即可冒泡的警告的线程安全方式.我也希望没有警告的方法保持不变.添加诸如yield或warning.warn的特殊构造警告气泡会很好.

So what I am looking for is a thread-safe way of bubbling warnings that does not require passing parameters. I also would like that methods that do not have warnings remain unchanged. Adding a special construct such as yield or warning.warn to bubble the warnings would be fine.

有什么想法吗?

推荐答案

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中的线程安全警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆