本文共 2694 字,大约阅读时间需要 8 分钟。
Gevent 是一个第三方库,能够轻松实现并发同步或异步编程,主要通过 Greenlet 模式以 C 扩展模块形式接入 Python。Greenlet 协程完全运行在主程序操作系统进程的内部,但通过协作式调度实现并发执行。
要使用 Gevent,首先需要执行以下操作:
import geventfrom gevent import monkey; monkey.patch_all()
这样可以确保 Gevent 能够识别并处理 I/O 阻塞。接下来,可以通过 gevent.spawn() 创建协程对象。例如:
g1 = gevent.spawn(eat, 1, 2, 3, x=4, y=5)
每个协程的执行流程如下:
def eat(): print('eat food 1') gevent.sleep(2) # 模拟 I/O 阻塞 print('eat food 2') 为了等待多个协程同时完成,可以使用 gevent.joinall() 方法:
g1 = gevent.spawn(eat)g2 = gevent.spawn(play_phone)gevent.joinall([g1, g2])print('主') 需要注意的是,gevent.sleep() 能够识别 I/O 阻塞操作,而 time.sleep() 等则需要通过 Gevent 的补丁机制才能识别。因此,在使用 Gevent 时,应确保在模块级别执行以下代码:
from gevent import monkey; monkey.patch_all()
这样可以让 Gevent 能够正确识别并处理所有需要的阻塞操作。
假设有一个简单的任务函数:
def task(pid): gevent.sleep(0.5) print('Task %s done' % pid) 可以通过以下方式同时执行多个任务:
import geventdef synchronous(): for i in range(1, 10): gevent.spawn(task, i)def asynchronous(): threads = [gevent.spawn(task, i) for i in range(10)] gevent.joinall(threads)print('Synchronous:')synchronous()print('Asynchronous:')asynchronous() 通过 gevent.joinall(),主程序会等待所有协程完成后才继续执行。
以下是一个基于 Gevent 的蜘蛛应用示例:
from gevent import monkey; monkey.patch_all()import geventimport requestsimport timedef get_page(url): print('GET: %s' % url) response = requests.get(url) if response.status_code == 200: print('%d bytes received from %s' % (len(response.text), url))start_time = time.time()gevent.joinall([ gevent.spawn(get_page, 'https://www.python.org/'), gevent.spawn(get_page, 'https://www.yahoo.com/'), gevent.spawn(get_page, 'https://github.com/'),])stop_time = time.time()print('run time is %s' % (stop_time - start_time)) 通过这种方式,可以同时下载多个网页内容。
以下是一个基于 Gevent 的 socket 服务器应用示例:
from gevent import monkey; monkey.patch_all()from socket import *import geventdef server(server_ip, port): s = socket(AF_INET, SOCK_STREAM) s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) s.bind((server_ip, port)) s.listen(5) while True: conn, addr = s.accept() gevent.spawn(talk, conn, addr)def talk(conn, addr): try: while True: res = conn.recv(1024) print('client %s:%s msg: %s' % (addr[0], addr[1], res)) conn.send(res.upper()) except Exception as e: print(e) finally: conn.close()if __name__ == '__main__': server('127.0.0.1', 8080) 客户端可以通过以下代码连接到服务器:
from socket import *client = socket(AF_INET, SOCK_STREAM)client.connect(('127.0.0.1', 8080))while True: msg = input('> >: ').strip() if not msg: continue client.send(msg.encode('utf-8')) msg = client.recv(1024) print(msg.decode('utf-8')) 通过 Gevent,可以轻松实现多协程的 socket 服务器应用。
转载地址:http://qclfk.baihongyu.com/