Skip to content

Instantly share code, notes, and snippets.

@noonat
Created February 19, 2017 04:43
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noonat/6526014c1c9fd0188d25aa4e10b2e520 to your computer and use it in GitHub Desktop.
Save noonat/6526014c1c9fd0188d25aa4e10b2e520 to your computer and use it in GitHub Desktop.
gevent + threads
"""This is an example of cooperating between a gevent hub and normal threads."""
import gevent
import socket as _socket
from gevent import hub, socket, _threading
conns = _threading.Queue()
def listen(watcher):
"""Listen for incoming connections.
This function runs in a separate Python thread. It doesn't use the gevent
primitives, and instead uses the normal Python ones. When it accepts a
connection, it sends a notification to the watcher (to wakeup the gevent
thread) and puts the connection into a thread safe queue.
:param watcher: gevent async watcher.
"""
s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM)
s.bind(('', 8080))
s.listen(5)
while True:
print 'listen: waiting for a connection'
conn, addr = s.accept()
print 'listen: accepted from', addr
watcher.send()
conns.put(conn)
print 'listen: appended to queue'
def on_connection():
"""Triggered whenever the listen function sends a notification.
Note that it's not permitted to block in this handler, so it just spawns
a new greenlet to handle the connection.
"""
print 'on_connection: spawning handler'
gevent.spawn(handle_connection)
def handle_connection():
"""Handles a single connection.
This is run in its own greenlet. It grabs a connection from the queue, and
handles it until the connection is closed. The connection from the queue
is not a gevent socket, but a normal Python socket, so this wraps the
socket in the gevent version.
"""
print 'handle_connection: getting connection'
conn = conns.get()
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM, _sock=conn)
print 'handle_connection: got connection'
f = conn.makefile()
for line in f:
print 'handle_connection:', repr(line)
conn.close()
print 'handle_connection: connection closed'
def ticker():
"""Prints a message once a second.
This is just a dummy ticker thread to show that the gevent loop is running.
"""
while True:
gevent.sleep(1)
print 'ticked'
watcher = hub.get_hub().loop.async()
watcher.start(on_connection)
_threading.start_new_thread(listen, (watcher,))
gevent.joinall([
gevent.spawn(ticker)
])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment