Monkey patching

from gevent import monkey
monkey.patch_all()

在开头的地方用了patch_all,会把标准库中的thread/socket等给替换掉,变成非阻塞的了.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
 #  @file       py_concurrent_download.py
 #  @brief
    ---------------------------------------------------------
    功能简介    Spawn multiple workers and wait for them to complete
    ---------------------------------------------------------
 #  @version    1.0.0
 #  @author     LindenTao(lindentao@qq.com)
 #  @date       2017/5/7 16:57
"""

from __future__ import print_function

import gevent
from gevent import monkey

# patches stdlib (including socket and ssl modules) to cooperate with other greenlets
monkey.patch_all()

import sys

urls = ['http://www.baidu.com', 'http://www.yandex.ru', 'http://www.qq.com', 'http://www.github.com']

if sys.version_info[0] == 3:
    from urllib.request import urlopen  # pylint:disable=import-error,no-name-in-module
else:
    from urllib2 import urlopen  # pylint: disable=import-error


def print_head(url):
    print('Starting %s' % url)
    data = urlopen(url).read()
    print('%s: %s bytes: %r' % (url, len(data), data[:50]))


jobs = [gevent.spawn(print_head, _url) for _url in urls]

gevent.wait(jobs)

用patch_all的结果(异步):
这里写图片描述
不用patch_all结果(同步):
这里写图片描述

数据结构

事件

import gevent
from gevent.event import Event

'''
Illustrates the use of events
'''

evt = Event()

def setter():
    '''After 3 seconds, wake all threads waiting on the value of evt'''
    print('A: Hey wait for me, I have to do something')
    gevent.sleep(3)
    print("Ok, I'm done")
    evt.set()

def waiter():
    '''After 3 seconds the get call will unblock'''
    print("I'll wait for you")
    evt.wait()  # blocking
    print("It's about time")


gevent.joinall([
    gevent.spawn(setter),
    gevent.spawn(waiter),
    gevent.spawn(waiter),
    gevent.spawn(waiter),
    gevent.spawn(waiter),
    gevent.spawn(waiter)
])

应用

简单server

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

'''
Created on 2016/08/16
File Name:py_gevent.py
author: LindenTao
Description : python gevent demo
'''

# On Unix: Access with ``$ nc 127.0.0.1 5000``
# On Window: Access with ``$ telnet 127.0.0.1 5000``

from gevent.server import StreamServer

def handle(socket, address):
    socket.send("Hello from a telnet!\n")
    for i in range(5):
        socket.send(str(i) + '\n')
    socket.close()

server = StreamServer(('127.0.0.1', 5000), handle)
server.serve_forever()

WSGI Servers

gevent.wsgi.WSGIServer
from gevent.wsgi import WSGIServer

def application(environ, start_response):
    status = '200 OK'
    body = '<p>Hello World</p>'

    headers = [
        ('Content-Type', 'text/html')
    ]

    start_response(status, headers)
    return [body]

WSGIServer(('', 8000), application).serve_forever()
gevent.pywsgi.WSGIServer
from gevent.pywsgi import WSGIServer

def application(environ, start_response):
    status = '200 OK'

    headers = [
        ('Content-Type', 'text/html')
    ]

    start_response(status, headers)
    yield "<p>Hello"
    yield "World</p>"

WSGIServer(('', 8000), application).serve_forever()

Long Polling

import gevent
from gevent.queue import Queue, Empty
from gevent.pywsgi import WSGIServer
import simplejson as json

data_source = Queue()

def producer():
    while True:
        data_source.put_nowait('Hello World')
        gevent.sleep(1)

def ajax_endpoint(environ, start_response):
    status = '200 OK'
    headers = [
        ('Content-Type', 'application/json')
    ]

    start_response(status, headers)

    while True:
        try:
            datum = data_source.get(timeout=5)
            yield json.dumps(datum) + '\n'
        except Empty:
            pass

gevent.spawn(producer)

WSGIServer(('', 8000), ajax_endpoint).serve_forever()

Gevent ZeroMQ

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

'''
Created on 2016/08/16
File Name:py_gevent.py
author: LindenTao
Description : python gevent demo
'''

# Note: Remember to ``pip install pyzmq gevent_zeromq``
import gevent
import zmq.green as zmq

# Global Context
context = zmq.Context()

def server():
    server_socket = context.socket(zmq.REQ)
    server_socket.bind("tcp://127.0.0.1:5000")

    for request in range(1, 10):
        server_socket.send("Hello")
        print('Switched to Server for %s' % request)
        # Implicit context switch occurs here
        server_socket.recv()

def client():
    client_socket = context.socket(zmq.REP)
    client_socket.connect("tcp://127.0.0.1:5000")

    for request in range(1, 10):

        client_socket.recv()
        print('Switched to Client for %s' % request)
        # Implicit context switch occurs here
        client_socket.send("World")

publisher = gevent.spawn(server)
client    = gevent.spawn(client)

gevent.joinall([publisher, client])

参考链接

赞助

如果您认为以上内容对您有所帮助和启发,不妨小额赞助我一下,让我有动力写出更好文章。
pay

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐