Path: csiph.com!usenet.pasdenom.info!goblin2!goblin.stu.neva.ru!newsfeed1.swip.net!uio.no!news.tele.dk!news.tele.dk!small.news.tele.dk!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.007 X-Spam-Evidence: '*H*': 0.99; '*S*': 0.00; 'example:': 0.03; '"__main__":': 0.09; '__name__': 0.09; 'callback': 0.09; 'exit': 0.09; 'main()': 0.09; 'cc:addr:python-list': 0.11; 'def': 0.12; './python': 0.16; '23,': 0.16; 'block.': 0.16; 'func': 0.16; 'loop.': 0.16; 'main():': 0.16; 'spawn': 0.16; 'true:': 0.16; 'sat,': 0.16; 'wrote:': 0.18; 'import': 0.22; 'putting': 0.22; 'separate': 0.22; 'cc:addr:python.org': 0.22; 'creating': 0.23; 'header:User-Agent:1': 0.23; 'instead.': 0.24; 'script.': 0.24; 'server.': 0.24; 'cc:2**0': 0.24; 'cc:no real name:2**0': 0.24; 'class.': 0.26; 'task': 0.26; 'header:In-Reply-To:1': 0.27; 'generally': 0.29; '+0100,': 0.31; 'class': 0.32; 'probably': 0.32; 'interface': 0.32; 'run': 0.32; 'running': 0.33; 'skip:_ 10': 0.34; 'could': 0.34; 'subject:with': 0.35; 'something': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'version': 0.36; 'yield': 0.36; 'done': 0.36; 'charset:us-ascii': 0.36; 'similar': 0.36; 'should': 0.36; 'two': 0.37; 'level': 0.37; 'nov': 0.38; 'tasks': 0.38; 'version,': 0.38; 'skip:p 20': 0.39; 'received:173': 0.61; 'content-disposition:inline': 0.62; "you'll": 0.62; 'name': 0.63; 'our': 0.64; 'more': 0.64; '20,': 0.68; ':).': 0.84; 'indefinitely': 0.84; 'phil': 0.84; 'toy': 0.84; '2013': 0.98 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=Lem1y0baJBEX6or1TYd5HRckRRGVdsMXGohGp3FW2ms=; b=g85QcjstD5Hve9CkXCIkeXD3Du8ClFvUT8BGQi5sLoN4m0DAYQnwUWNqGBB/Ah/GpE J+LrrukK6qzk0vEP04jpyLk7FsIMDUxizXlxoyKmtjXcUN0PdnlvRHvSAe4xj/IjKwTD zEJPGs7b2Oa6WtVTqLE5fkRKKui9pjn8uFONeD5hZpLmtPBBBBvPM30kxQxnYklu9YIy xvJW6MPbFwwYtp3xAG3S6uwvUxggefJnfTv26GWV2IeMZB4wW8hH8z/Q8MjkKwOLMbDU NqxCLY+3o1pZ9VwTyJkFpLB591Wh2My0BYLp3OMLEDsw/r0htK35ROVK9bKff1NO92uz VDRg== X-Received: by 10.194.20.202 with SMTP id p10mr1571689wje.39.1385376776772; Mon, 25 Nov 2013 02:52:56 -0800 (PST) Date: Mon, 25 Nov 2013 10:52:54 +0000 From: Phil Connell To: "Tobias M." Subject: Re: Periodic execution with asyncio References: <528FCCF2.4020608@tobix.eu> <52911065.6080308@tobix.eu> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <52911065.6080308@tobix.eu> User-Agent: Mutt/1.5.22 (2013-10-16) Cc: python-list@python.org X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 76 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1385377101 news.xs4all.nl 15969 [2001:888:2000:d::a6]:41668 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:60408 On Sat, Nov 23, 2013 at 09:30:29PM +0100, Tobias M. wrote: > Now putting this into a PeriodicTask class that provides a similar interface > like our callback version, I get: > > > import asyncio > > class PeriodicTask2(object): > > def __init__(self, func, interval): > self.func = func > self.interval = interval > self._loop = asyncio.get_event_loop() > > def start(self): > self.loop.run_until_complete(asyncio.Task(self._run())) > > @asyncio.coroutine > def _run(self): > while True: > yield from asyncio.sleep(self.interval) > self.func() > > > I don't know if I misunderstood anything, but as a user of this class I am > not able to run two task simultaneously because start() will block. In the > callback version I could instanciate two PeriodicTasks and run them both at > the same time (after a call to loop.run_forever()), which is actually what I > wanted to achieve with this class. You need to separate out creating tasks from running the event loop. Specifically, you should run the event loop in exactly one place, probably at the top level of your script. A toy example: import asyncio @asyncio.coroutine def adder(*args, delay): yield from asyncio.sleep(delay) print(sum(args)) def main(): asyncio.Task(adder(1, 2, 3, delay=5)) asyncio.Task(adder(10, 20, delay=3)) loop = asyncio.get_event_loop() loop.run_forever() if __name__ == "__main__": main() $ ./python test.py 30 6 Note that run_forever() will block indefinitely (as the name suggests :). This is generally what you'll want for a long-running server. If you want do something more like: - Spawn some tasks - Run the event loop until they're done - Exit then you'll need to use loop.run_until_complete(asyncio.gather(*tasks)) instead. HTH, Phil