Python 中的线程安全警告
我试图找到一种好方法来记录警告消息,但附加只有函数调用者知道的信息。
我想通过一个例子就很清楚了。
# 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 中的最后一个 QA)。此外,我不确定这种类型的实现是否还有其他问题。
所以我正在寻找的是一种不需要传递参数的线程安全的冒泡警告方式。我还希望没有警告的方法保持不变。添加一个特殊的构造,例如yield或warning.warn来冒泡警告就可以了。
有什么想法吗?
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()
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()
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.
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.
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
产量
yields