3
我正試圖找到一種很好的方式來記錄警告消息,但追加了只有函數調用方纔知道的信息。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產生(而不是返回)的最終結果是不方便,因爲函數將不得不明確地改變爲以這種方式使用(也許這將在未來改變?最後QA PEP255)。另外,我不確定這種類型的實現是否存在其他問題。
所以我在尋找的是一個線程安全的冒泡警告方式,不需要傳遞參數。我也希望那些沒有警告的方法保持不變。添加一個特殊的構造如yield或warning.warn來冒泡警告就沒有問題。
任何想法?
感謝您的建議,但是這仍然需要我給記錄器亞軍,我沒有看到我比較例1任何好處。 – Hernan
@Hernan:你能提供一些你想要的'Runner'的樣子嗎?您如何期望在Runner中使用記錄器而不將記錄器明確傳遞給Runner?通過使用全局變量?關閉?這兩個選項似乎都不太吸引我... – unutbu
其實,我的例子2和3更多的是我所尋找的。保持跑步者簡單,併爲調用跑步者的功能添加一些複雜性。如果它是線程安全的,則示例2將是完美的。如果我可以「返回42」(而不是yield 42),則示例3將是完美的,因爲這意味着沒有警告的函數將不加修改地運行。 – Hernan