@asyncio.coroutine defget_url(url): wait_time = random.randint(1, 4) yieldfrom asyncio.sleep(wait_time) print('URL {} took {}s to get!'.format(url, wait_time)) return url, wait_time
@asyncio.coroutine defprocess_as_results_come_in(): before = time.time() coroutines = [get_url(url) for url in ['URL1', 'URL2', 'URL3']] for coroutine in asyncio.as_completed(coroutines): url, wait_time = yieldfrom coroutine print('Coroutine for {} is done'.format(url)) after = time.time() print('total time: {} seconds'.format(after - before))
@asyncio.coroutine defprocess_once_everything_ready(): before = time.time() coroutines = [get_url(url) for url in ['URL1', 'URL2', 'URL3']] results = yieldfrom asyncio.gather(*coroutines) print(results) after = time.time() print('total time: {} seconds'.format(after - before))
defmain(): loop = asyncio.get_event_loop() print("First, process results as they come in:") loop.run_until_complete(process_as_results_come_in()) print("\nNow, process results once they are all ready:") loop.run_until_complete(process_once_everything_ready())
if __name__ == '__main__': main()
代码输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$ python3 asyncio_test.py First, process results as they come in: URL URL3 took 1s to get! Coroutine for URL3 is done URL URL2 took 2s to get! Coroutine for URL2 is done URL URL1 took 3s to get! Coroutine for URL1 is done total time: 3.001127004623413 seconds
Now, process results once they are all ready: URL URL1 took 1s to get! URL URL3 took 1s to get! URL URL2 took 4s to get! [('URL1', 1), ('URL2', 4), ('URL3', 1)] total time: 4.004215955734253 seconds
import random import time from tornado import gen from tornado.ioloop import IOLoop
@gen.coroutine defget_url(url): wait_time = random.randint(1, 4) yield gen.sleep(wait_time) print('URL {} took {}s to get!'.format(url, wait_time)) raise gen.Return((url, wait_time))
@gen.coroutine defprocess_once_everything_ready(): before = time.time() coroutines = [get_url(url) for url in ['URL1', 'URL2', 'URL3']] result = yield coroutines after = time.time() print(result) print('total time: {} seconds'.format(after - before))
@gen.coroutine defprocess_once_everything_ready_2(): before = time.time() coroutines = [get_url(url) for url in ['URL1', 'URL2', 'URL3']] results = yield gen.Multi(coroutines) after = time.time() print(results) print('total time: {} seconds'.format(after - before))
@gen.coroutine defprocess_as_results_come_in(): before = time.time() coroutines = [get_url(url) for url in ['URL1', 'URL2', 'URL3']] wait_iterator = gen.WaitIterator(*coroutines) whilenot wait_iterator.done(): url, wait_time = yield wait_iterator.next() print('Coroutine for {} is done'.format(url)) after = time.time() print('total time: {} seconds'.format(after - before))
@gen.coroutine defamazing_test(): before = time.time() coroutines = [get_url(url) for url in ['URL1', 'URL2', 'URL3']] yield gen.sleep(5) after = time.time() print('total time: {} seconds'.format(after - before))
@gen.coroutine defprocess_together_or_once_depend_on_the_sequence(): before = time.time() coroutines = [get_url(url) for url in ['URL1', 'URL2', 'URL3']] for future in coroutines: url, wait_time = yield future print('Coroutine for {} is done'.format(url)) after = time.time() print('total time: {} seconds'.format(after - before))
if __name__ == '__main__': print("First, process results as they come in:") IOLoop.current().run_sync(process_as_results_come_in) print("\nNow, process results once they are all ready:") IOLoop.current().run_sync(process_once_everything_ready) print("\nprocess results once they are all ready 2:") IOLoop.current().run_sync(process_once_everything_ready_2) print("\nAmazing test:") IOLoop.current().run_sync(amazing_test) print("\nprocess_together_or_once_depend_on_the_sequence:") IOLoop.current().run_sync(process_together_or_once_depend_on_the_sequence)
$ python3 tornado_test.py First, process results as they come in: URL URL2 took 2s to get! Coroutine for URL2 is done URL URL1 took 3s to get! URL URL3 took 3s to get! Coroutine for URL1 is done Coroutine for URL3 is done total time: 3.00437688828 seconds
Now, process results once they are all ready: URL URL2 took 1s to get! URL URL3 took 1s to get! URL URL1 took 4s to get! [('URL1', 4), ('URL2', 1), ('URL3', 1)] total time: 4.000649929046631 seconds
process results once they are all ready 2: URL URL2 took 1s to get! URL URL3 took 1s to get! URL URL1 took 4s to get! [('URL1', 4), ('URL2', 1), ('URL3', 1)] total time: 4.004122018814087 seconds
Amazing test: URL URL3 took 1s to get! URL URL1 took 2s to get! URL URL2 took 4s to get! total time: 5.004791975021362 seconds
nprocess_together_or_once_depend_on_the_sequence: URL URL1 took 1s to get! URL URL3 took 1s to get! Coroutine for URL1 is done URL URL2 took 2s to get! Coroutine for URL2 is done Coroutine for URL3 is done total time: 2.0033011436462402 seconds
tornado的例子,参考了官方文档我给了5个(为啥框架提供这么多?选择太多反而不好,不是吗)。在这里,所有例子总的运行时间都是等于最长的协程的运行时间,这点合理!在这5个例子中,我给了一个 Amazing test ,因为自己乱试,看到这个效果的时候,感觉对tornado的三观有点被毁了,不过后来还是搞懂了,下面我就来解释一下。