不使用多线程, 使用select, 实现http请求的异步

使用select实现ioloop, 实现http请求异步,有利于理解select(epool)模型, 代码如下:


#!/bin/python

import select
import time
from http.client import HTTPConnection

class Handler(object):
        pass

class AsyncHTTPHandler(Handler):

        def __init__(self, url, io_loop, callback):

                self.http_conn = HTTPConnection(url)
                self.url = url
                self.io_loop = io_loop
                self.callback = callback
                self.http_conn.connect()
                self.fileno = self.http_conn.sock.fileno
                print ("has conn:", self.http_conn, " fileno:", self.fileno())
                self.can_recv = False
                self.can_send = True
                self.io_loop.add_handler(self)

        def wants_recv(self):
                return self.can_recv

        def wants_send(self):
                return self.can_send

        def fileno(self):
                return self.fileno

        def handler_recv(self):
                resp = self.res.read()
                self.io_loop.remove_handler(self)
                print ("Resp:",self.url,self.http_conn, self.res)
                if self.callback:
                        callback(resp)


        def handler_send(self):
                print("Request:", self.url, self.http_conn)
                self.http_conn.request("GET", "/", None, {})
                self.res = self.http_conn.getresponse()
                self.can_send = False
                self.can_recv = True


class IOLoop(object):

        handlers = []
        def __init__(self):
                pass

        def event_loop():
                handlers = IOLoop.handlers
                while True:
                        r = [h for h in handlers if h.wants_recv()]
                        s = [h for h in handlers if h.wants_send()]
                        can_recv, can_send, err = select.select(r, s, [])
                        for h in can_recv:
                                h.handler_recv()
                        for h in can_send:
                                h.handler_send()

        @staticmethod
        def add_handler(h):
                IOLoop.handlers.append(h)

        @staticmethod
        def remove_handler(h):
                IOLoop.handlers.remove(h)


class AsyncHTTPClient(object):
        """
        """

        def __init__(self, io_loop=None):
                self.io_loop = io_loop or IOLoop

        def fetch(self, url, io_loop=None, callback=None):
                self.callback = callback
                h = AsyncHTTPHandler(url, self.io_loop, callback)



# --- test code ---- #
def callback(r):
        print("callback", r[:100])

def test():
        http_client = AsyncHTTPClient()
        t3 = time.time()
        http_client.fetch("www.baidu.com", callback=callback)
        http_client.fetch("www.python.org", callback=callback)
        t4 = time.time()
        print ("t4-t3", t4-t3)
        #http_client.fetch("www.google.com", callback=callback)
        IOLoop.event_loop()
        print("==== loop start ====")

if __name__ == "__main__":
        test()


打印:


has conn: <http.client.HTTPConnection object at 0x7faac8abd470>  fileno: 3
has conn: <http.client.HTTPConnection object at 0x7faac82e2400>  fileno: 4
t4-t3 0.13575148582458496
Request: www.baidu.com <http.client.HTTPConnection object at 0x7faac8abd470>
Request: www.python.org <http.client.HTTPConnection object at 0x7faac82e2400>
Resp: www.baidu.com <http.client.HTTPConnection object at 0x7faac8abd470> <http.client.HTTPResponse object at 0x7faac82e2780>
callback b'<!DOCTYPE html><!--STATUS OK-->\r\n<html>\r\n<head>\r\n\t<meta http-equiv="content-type" content="text/html'
Resp: www.python.org <http.client.HTTPConnection object at 0x7faac82e2400> <http.client.HTTPResponse object at 0x7faac82e2940>
callback b''

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值