已复制
全屏展示
复制代码

Python异步非阻塞多种实现方式


· 1 min read

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()
    
🔗

文章推荐