我有一个source
可观察对象,我订阅logger
观察者用于记录目的。
我还订阅了source
,因此我可以执行计算。当我的计算完成后,我已完成source
并且我想处理logger
:
+-------------------+
| |
+---------+ source observable +--------+
| | | |
| +-------------------+ |
| |
| |
+--v---------------+ +------------v--------+
| | | |
| logger | | computations |
| (observer) | | (observable) |
+-------^----------+ +-----------+---------+
| |
| |
| dispose logger |
+--------------------------------+
when computations completed
然而,logger
并未在正确的时间处理 - 通常会发生一两个额外的滴答声:
from rx import Observable
# Some source
source = Observable.interval(1)
# Create logger for source
logged = []
logger = source.subscribe(logged.append)
# Now do stuff/computations with source
calculated = source.map(lambda x: x**2).take_while(lambda x: x < 20)
# Output computed values and stop logging when we're done with our computation
calculated.subscribe(print, print, logger.dispose)
# I expect only values that passed through our computation to have been logged
# The last value should be 5 because 5**2 = 25 which is larger than 20
# which in turn causes our computation to terminate
assert logged == [0, 1, 2, 3, 4, 5], logged
但我明白了:
Traceback (most recent call last):
File "C:\Program Files (x86)\Python27\lib\site-packages\IPython\core\interactiveshell.py", line 3035, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-54-e8cb1fb583bf>", line 1, in <module>
assert logged == [0, 1, 2, 3, 4, 5], logged
AssertionError: [0, 1, 2, 3, 4, 5, 6, 7]
7如何记录?我们的计算应在source
发出5之后终止,此时logger
将被处理掉。
我做错了什么?
答案 0 :(得分:0)
这是线程同步问题。 interval()
运算符启动新线程以在指定的时间间隔内调用on_next()
。处理完订阅后,需要一些时间,直到其他线程检测到此信号并停止工作。并且一毫秒接近它所需的时间。
为了记录通过反应链的消息,将记录功能直接插入该链是更可靠的:
logged = []
def logger(x):
logged.append(x)
return x
calculated = source \
.map(logger) \
.map(lambda x: x**2) \
.take_while(lambda x: x < 20) \
.subscribe(print, print)