Issue
I'm having trouble wrapping my head around how coroutines are chained together. In a slightly less trivial example than hello world or factorials, I'd like to have a loop which continually watches file modification times, and then prints out the time whenever the file is touched:
#!/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()
I would expect this to work - however, when I run it I get a:
RuntimeError: Task got bad yield: 1426449327.2590399
What am i doing wrong here?
UPDATE: see my answer below for an example of the observer pattern (i.e. efficiently allow multiple registrants to get updates when a file gets touched) without using callbacks (you have to use Tasks).
UPDATE2: there is a better fix for this: 3.5's async for
(asynchronous iterators): https://www.python.org/dev/peps/pep-0492/
Solution
I got your code working by using return
instead of yield
in the chained coroutine, just like the chained coroutines example:
#!/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()
Note that printer()
's loop will create a new pathmonitor
generator for each iteration. Not sure if this is what you had in mind but it might be a start.
I find the coroutines API and syntax a bit confusing myself. Here's some reading that I have found helpful:
- What’s New In Python 3.3: "PEP 380: Syntax for Delegating to a Subgenerator"
- PEP380: "Formal semantics"
- asyncio: "Example: Chain coroutines"
- Greg Ewing's "Binary Tree" example
Answered By - André Laszlo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.