Skip to content

Instantly share code, notes, and snippets.

@cosven
Last active October 2, 2018 07:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cosven/a251ca10c6c0c57c8b5dbd92fe131c2f to your computer and use it in GitHub Desktop.
Save cosven/a251ca10c6c0c57c8b5dbd92fe131c2f to your computer and use it in GitHub Desktop.
how gevent works?
# gevent from the ground up - demo 1
import selectors
import socket
import time
from urllib.parse import urlparse
sel = selectors.DefaultSelector()
class Task(object):
def __init__(self):
self._state = 'STARTED'
self.result = None
def set_result(self, result):
self.result = result
self._state = 'FINISHED'
@property
def done(self):
return self._state == 'FINISHED'
class HttpRequest(object):
def __init__(self, method, url):
self._method = method
self._url = url
self._buf = bytearray()
self._task = Task()
def start(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
parse_result = urlparse(self._url)
sock.connect((parse_result.hostname, parse_result.port or 80))
sock.send(b'%b / HTTP/1.1\r\n\r\n' % bytes(self._method, 'ascii'))
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, self._read_cb)
yield self._task
def _read_cb(self, conn, mask):
data = conn.recv(16)
if data == b'':
self._task.set_result(self._buf[:])
sel.unregister(conn)
conn.close()
return True
self._buf.extend(data)
class Hub(object):
def __init__(self):
self.to_finish = {}
def run(self):
# event loop
while 1:
if not self.to_finish:
yield self
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
if all([task.done for task in self.to_finish.values()]):
self.to_finish = {}
hub = Hub()
hub_coro = hub.run()
def spawn(coro):
task = next(coro)
return task
def joinall(tasks):
for task in tasks:
hub.to_finish[id(task)] = task
try:
next(hub_coro)
except StopIteration:
pass
tasks = [spawn(HttpRequest('GET', 'http://www.douban.com').start()),
spawn(HttpRequest('GET', 'http://www.example.org').start())]
start = time.time()
joinall(tasks)
print('async', time.time() - start)
@cosven
Copy link
Author

cosven commented Jul 25, 2018

  • 一个生成器相当与一个 greenlet
  • Hub 和 gevent 中的 Hub 有点相似

通过这个例子,可以了解

  • gevent 的大致工作原理
  • greenlet 调度机制?

据说 greenlet 的调度原理也很值得研究,但目前还不太懂。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment