python yield实现原理_Python async io原理 yield实现

from selectors import DefaultSelector, EVENT_WRITE, EVENT_READ

from socket import socket

from urllib.parse import urlparse

class Future:

def __init__(self):

self.result = None

self.call_backs = []

def add_done_callback(self, func):

self.call_backs.append(func)

def set_result(self, result):

self.result = result

for call in self.call_backs:

call(self)

class Task:

_tasks = []

def __init__(self, coroutine):

self.coroutine = coroutine

self._tasks.append(coroutine)

f = Future()

self.step(f)

def step(self, future):

try:

next_future = self.coroutine.send(future.result)

except StopIteration as e:

self._tasks.remove(self.coroutine)

print(e.value)

return e.value

next_future.add_done_callback(self.step)

class Loop:

__instance = None

selector = DefaultSelector()

def __new__(cls, *args, **kwargs):

if cls.__instance is None:

cls.__instance = super().__new__(cls, *args, **kwargs)

return cls.__instance

def run_until_complete(self):

while Task._tasks:

for key, mask in self.selector.select():

callback = key.data

callback()

class Spider:

def __init__(self, url):

self.url = url

self.host = urlparse(self.url).netloc

self.path = urlparse(self.url).path

self.r = b''

def fetch(self):

sock = socket()

sock.setblocking(False)

try:

sock.connect((self.host, 80))

except BlockingIOError:

pass

f = Future()

def send():

f.set_result(None)

Loop.selector.register(sock.fileno(), EVENT_WRITE, send)

yield f

sock.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format(self.path, self.host).encode("utf8"))

Loop.selector.unregister(sock.fileno())

def read():

f.set_result(sock.recv(1024))

Loop.selector.register(sock.fileno(), EVENT_READ, read)

while True:

f = Future()

chunk = yield f

if chunk:

self.r += chunk

else:

Loop.selector.unregister(sock.fileno())

sock.close()

break

self.r = self.r.decode().split('\r\n\r\n')[1]

return self.r

if __name__ == '__main__':

for i in range(1, 30):

url = "http://shop.projectsedu.com/goods/{}/".format(i)

spider = Spider(url)

Task(spider.fetch())

loop = Loop()

loop.run_until_complete()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值