我有一个带有解析器的第三方库,它需要一个带有new_token
方法的回调类。到目前为止,我的回调类和我的令牌处理如下所示:
class MySink(object):
def __init__(self):
self.tokens = []
def new_token(self, token):
self.tokens.append(token)
sink = MySink()
p = ThirdPartyParser(sink)
p.parse("my_data_file")
for t in sink.tokens:
print t
令牌列表可能会变得很长(导致内存问题)所以我想将MySink
变成一个可迭代的类,其中令牌不必存储在列表中但是被“拉”在处理令牌时停止解析。像这样:
class MyIterableSink(object): # incomplete!
def new_token(self, token):
# TODO:
# Store token for next iteration step
# halt execution like with 'yield', wait for next iteration step
sink = MyIterableSink()
p = ThirdPartyParser(sink)
p.parse("my_data_file")
for t in sink:
print t
如何修改MyIterableSink
课程?这样的事情可能吗?我无法修改解析器类,只能修改回调类。我知道我必须实现__iter__
和__next__
方法并使用协同程序,其中可能使用send
方法发送令牌,但不能完全绕过它。任何代码示例都将不胜感激。
答案 0 :(得分:1)
该行
p.parse("my_data_file")
必须在循环中调用new_token
。由于您无法改变第三方解析器的工作方式,因此您无法控制new_token
被调用的方式。由于MySink
没有迭代p.parse
,因此使sink
迭代器无效。因此,不要将sink
设为迭代器,只需在调用new_token
时处理标记:
class MySink(object):
def new_token(self, token):
# process token
print(token)
sink = MyIterableSink()
p = ThirdPartyParser(sink)
p.parse("my_data_file")
答案 1 :(得分:0)
如果回调是异步的,您可以使用Queue:
class MySink(object):
def __init__(self):
self.tokens = Queue()
def new_token(self, token):
self.tokens.put(token)
def __iter__(self):
token = self.tokens.get()
while token is not None:
yield token
token = self.tokens.get()
请注意,您必须为迭代器指定停止条件,例如超时或特殊标记值(上例中的None
)。
编辑: 由于你的回调是同步的,unutbu在他的answer中说了这一切。