我很难理解协同程序是如何链接在一起的。在一个比hello world或factorials稍微简单一些的示例中,我希望有一个循环,它可以持续监视文件修改时间,然后在触摸文件时打印出时间:
#!/usr/bin/env python3
import os
import asyncio
@asyncio.coroutine
def pathmonitor(path):
modtime = os.path.getmtime(path)
while True:
new_time = os.path.getmtime(path)
if new_time != modtime:
modtime = new_time
yield modtime
yield from asyncio.sleep(1)
@asyncio.coroutine
def printer():
while True:
modtime = yield from pathmonitor('/home/users/gnr/tempfile')
print(modtime)
loop = asyncio.get_event_loop()
loop.run_until_complete(printer())
loop.run_forever()
我希望这可以工作-然而,当我运行它时,我得到一个:
RuntimeError: Task got bad yield: 1426449327.2590399
我做错了什么?
更新:请参阅下面我的答案,以了解观察者模式的示例(即,当文件被触动时,有效地允许多个注册者获取更新),而无需使用回调(您必须使用任务)。
UPDATE2:有一个更好的解决方案:3.5的async for
(异步迭代器):https://www.python.org/dev/peps/pep-0492/
正如其他人指出的那样,我的错误是,我试图像发电机一样使用协同程序。我需要创建多个协程,而不是依赖生成器进行迭代。此外,我需要使用任务来实现观察者模式,而不需要回调,因为多个注册者可以从同一个任务中产生。我的pathmonitor看起来像这样:
import os
import asyncio
class PathInfo:
def __init__(self, path):
self.path = path
self.modtime = os.path.getmtime(path)
self.startTask()
def startTask(self):
self.task = asyncio.async(self._checkIfTouched())
def _checkIfTouched(self):
while True:
yield from asyncio.sleep(1)
newtime = os.path.getmtime(self.path)
if self.modtime != newtime:
self.modtime = newtime
return newtime
class PathMonitor:
def __init__(self):
self._info = {}
@asyncio.coroutine
def wasTouched(self, path):
try:
info = self._info[path]
except KeyError:
self._info[path] = info = PathInfo(path)
if info.task.done():
info.startTask()
modtime = yield from info.task
return modtime
def printer():
while True:
modtime = yield from mon.wasTouched('/tmp/myfile')
print(modtime)
mon = PathMonitor()
loop = asyncio.get_event_loop()
asyncio.async(printer())
loop.run_forever()
我通过在链式协同路由中使用return而不是
yield来运行代码,就像链式协同路由示例一样:
#!/usr/bin/env python3
import os
import asyncio2
@asyncio.coroutine
def pathmonitor(path):
modtime = os.path.getmtime(path)
while True:
new_time = os.path.getmtime(path)
if new_time != modtime:
modtime = new_time
return modtime
yield from asyncio.sleep(1)
@asyncio.coroutine
def printer():
while True:
modtime = yield from pathmonitor('/tmp/foo.txt')
print(modtime)
loop = asyncio.get_event_loop()
loop.run_until_complete(printer())
loop.run_forever()
请注意,
打印机()
的循环将为每次迭代创建一个新的路径监视器
生成器。不确定这是否是您想要的,但这可能是一个开始。
我发现协程API和语法让我自己有点困惑。以下是一些我觉得有用的阅读材料:
Python 3.3中的新增功能:“PEP 380:委托给子生成器的语法”
- PEP380:"形式语义学"
- asyncio:"示例:链协程"
- Greg Ewing的“二叉树”例子
是否有一种设计模式可以形成一个“复合”观察者/可观察者? 我的意思是我有一个可观察的,它在某个变化时通知它的监听器。 每个监听器也是一个可观察的,并通知它自己的监听器(在某个动作上,它做了哪个动作是由第一个可观察的通知触发的)。 这种观察者/可观察的“链接”作为设计是可以的,还是有一个标准的模式?
主要内容:介绍,实现,Subject.java,Observer.java,BinaryObserver.java,OctalObserver.java,HexaObserver.java,ObserverPatternDemo.java当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。 介绍 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知
观察者模式 亦称: 事件订阅者、监听者、Event-Subscriber、Listener、Observer 意图 观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。 问题 假如你有两种类型的对象: 顾客和 商店 。 顾客对某个特定品牌的产品非常感兴趣 (例如最新型号的 iPhone 手机), 而该产品很快将会在商店里出售。 顾客
一、定义 观察者模式(发布-订阅模式):其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。 在JavaScript中,一般使用事件模型来替代传统的观察者模式。 好处: (1)可广泛应用于异步编程中,是一种替代传递回调函数的方案。 (2)可取代对象之间硬编码的通知机制,一个对象不用再显示地调用另外一个对象的某个接口。两对象轻松解耦。 二、DOM事件–观察者
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 介绍 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。 何时使用:一个对象(目标对象)
观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。 定义一个目标构造函数,并实现绑定、解绑和触发等方法: function Subject() { this.events = {}; this.count = 0; } Subj