Python异步非阻塞多种实现方式
Python 回调函数
回调函数的原大概就是下面代码的样子,deal_with
函数是真正执行计算的函数,计算后需要通知调用者计算结果,通过传入的get_result
函数处理计算结果。
import time
def get_result(x):
print(f'this is process result: {x}')
def deal_with(x, callback):
time.sleep(1)
result = x ** 2
callback(result)
def main():
deal_with(2, get_result)
deal_with(3, get_result)
if __name__ == '__main__':
main()
Tornado 异步非阻塞
同步函数
from tornado.httpclient import HTTPClient
def synchronous_fetch(url):
http_client = HTTPClient()
response = http_client.fetch(url)
return response.body
原生协程实现异步
from tornado.httpclient import AsyncHTTPClient
async def asynchronous_fetch(url):
http_client = AsyncHTTPClient()
response = await http_client.fetch(url)
return response.body
Future 方式实现异步
from tornado.concurrent import Future
from tornado.httpclient import AsyncHTTPClient
def async_fetch_manual(url):
http_client = AsyncHTTPClient()
my_future = Future()
fetch_future = http_client.fetch(url)
def on_fetch(f):
my_future.set_result(f.result().body)
fetch_future.add_done_callback(on_fetch)
return my_future
回调方式实现异步
调用异步函数async_fetch
,同时传入一个回调函数。 async_fetch
处理完请求后,调用函数handle_response
将结果返回。
from tornado.httpclient import AsyncHTTPClient
def async_fetch(url, callback):
def handle_response(response):
callback(response.body)
client = AsyncHTTPClient()
client.fetch(url, callback=handle_response)
asyncio异步网络请求
import re
import asyncio
import threading
@asyncio.coroutine
def fetch(host, port=80):
reader, writer = yield from asyncio.open_connection(host, port)
request = 'GET / HTTP/1.0\r\n\r\n'
writer.write(request.encode('utf-8'))
body = yield from reader.read()
body = body.decode('utf-8')
title = re.search(r'<title>(.*)</title>', body)
title = title.group(1) if title else None
print(title, threading.currentThread())
def main():
loop = asyncio.get_event_loop()
hosts = ['www.baidu.com', 'news.qq.com', 'music.taihe.com', 'v.baidu.com']
tasks = [fetch(host) for host in hosts]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
if __name__ == '__main__':
main()