To do this in a single thread, you will have to use non-blocking methods and combine them into a single event loop. I use select instead of the non-blocking input / output of the socket here, since it is a bit clean if you need to read from multiple sockets ...
import socket import select import Queue import time TIMEOUT = 0.1 # 100ms def process_queue_item(item): print 'Got queue item: %r' % item def process_socket_data(data): print 'Got socket data: %r' % data def main(): # Build queue queue = Queue.Queue() for i in range(10): queue.put(i) queue.put(None) # Using None to indicate no more data on queue queue_active = True # Build socket sock = socket.socket() sock.connect(('www.google.com', 80)) sock.send('GET / HTTP/1.0\r\n\r\n') socket_active = True # Main event loop while 1: # If there nothing to read, bail out if not (socket_active or queue_active): break # By default, sleep at the end of the loop do_sleep = True # Get data from socket without blocking if possible if socket_active: r, w, x = select.select([sock], [], [], TIMEOUT) if r: data = sock.recv(64) if not data: # Hit EOF socket_active = False else: do_sleep = False process_socket_data(data) # Get item from queue without blocking if possible if queue_active: try: item = queue.get_nowait() if item is None: # Hit end of queue queue_active = False else: do_sleep = False process_queue_item(item) except Queue.Empty: pass # If we didn't get anything on this loop, sleep for a bit so we # don't max out CPU time if do_sleep: time.sleep(TIMEOUT) if __name__ == '__main__': main()
The conclusion looks like ...
Got socket data: 'HTTP/1.0 302 Found\r\nLocation: http://www.google.co.uk/\r\nCache-Co' Got queue item: 0 Got socket data: 'ntrol: private\r\nContent-Type: text/html; charset=UTF-8\r\nSet-Cook' Got queue item: 1 Got socket data: 'ie: PREF=ID=a192ab09b4c13176:FF=0:TM=1373055330:LM=1373055330:S=' Got queue item: 2 etc.
source share