Last active
December 23, 2015 03:24
-
-
Save alex8224/6fa0a1758485b93b37fd to your computer and use it in GitHub Desktop.
call async io function in coroutine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding:utf-8 -*- | |
from tornado.gen import coroutine | |
from tornado.concurrent import Future | |
from tornado.ioloop import IOLoop | |
from tornado.httpclient import AsyncHTTPClient | |
from functools import wraps, partial | |
ioloop = IOLoop.instance() | |
AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient") | |
httpclient = AsyncHTTPClient() | |
class Return(Exception): | |
def __init__(self, value): | |
super(Return, self).__init__() | |
self._value = value | |
@property | |
def value(self): | |
return self._value | |
def subcoroutine(func): | |
final_future = Future() | |
def _continue_yield(result, future): | |
try: | |
tmp_result = result.send(future.result()) | |
if isinstance(tmp_result, Future): | |
ioloop.add_callback(_io_callback, result, tmp_result) | |
else: | |
raise Exception("only support yield future") | |
except StopIteration: | |
final_future.set_result(None) | |
except Return as rvalue: | |
final_future.set_result(rvalue.value) | |
except Exception as ex: | |
final_future.set_exception(ex) | |
def _io_callback(result, attach=None): | |
if isinstance(attach, Future): | |
ioloop.add_future(attach, partial(_continue_yield, result)) | |
@wraps(func) | |
def inner_call(*args, **kwargs): | |
result = func(*args, **kwargs) | |
attach = result.send(None) | |
ioloop.add_callback(_io_callback, result, attach) | |
return final_future | |
return inner_call | |
@subcoroutine | |
def step1(url): | |
print("step1, fetch %s url" % url) | |
response = yield httpclient.fetch(url) | |
print("step1, fetch %s url ok , http code is:%d" % (url, response.code)) | |
raise Return(response) | |
@subcoroutine | |
def step2(url): | |
print("fetch %s" % url) | |
response = yield httpclient.fetch(url) | |
print("%s url fetch ok, the http code is:%d" % (url, response.code)) | |
raise Return(response) | |
@subcoroutine | |
def call_other_coroutine(url, url2): | |
response = yield httpclient.fetch(url) | |
print("%s fetch ok" % url) | |
yield step2(url2) | |
print("%s fetch ok" % url2) | |
@coroutine | |
def start(): | |
response = yield step1("https://www.baidu.com") | |
print("https://www.yahoo.com", response.headers) | |
response = yield step2("http://www.baidu.com") | |
print("http://www.apple.com", response.headers) | |
yield call_other_coroutine("https://news.ycombinator.com/", "http://www.quora.com") | |
ioloop.run_sync(start) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment