python - gevent 模块生成的 greenlet 对象,要如何启动?

查看:115
本文介绍了python - gevent 模块生成的 greenlet 对象,要如何启动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

以前以为:gevent 模块生成的 greenlet 对象,需要用 join 或 joinall 来启动。例如:

# /usr/bin/env python3
# -*- encoding:utf-8 -*-

from gevent import monkey; monkey.patch_all()
import gevent,urllib.request

def f(url):
    print('GET: %s' % url)
    resp = urllib.request.urlopen(url)
    data = resp.read()
    print('%d bytes received from %s.' % (len(data), url))

gevent.joinall([
        gevent.spawn(f, 'https://www.python.org/'),
        gevent.spawn(f, 'https://www.yahoo.com/'),
        gevent.spawn(f, 'https://github.com/'),
])

但是有一次看到一个 通过单线程实现多socket并发 的例子:

服务端:

# /usr/bin/env python3
# -*- encoding:utf-8 -*-

import socket, gevent
from gevent import socket, monkey;monkey.patch_all()


def server(port):
    s = socket.socket()
    s.bind(('0.0.0.0', port))
    s.listen(500)
    while True:
        cli, addr = s.accept()
        gevent.spawn(handle_request, cli)


def handle_request(conn):
    try:
        while True:
            data = conn.recv(1024)
            print("recv:", data)
            conn.send(data)
            if not data:
                conn.shutdown(socket.SHUT_WR)

    except Exception as  ex:
        print(ex)
    finally:
        conn.close()


if __name__ == '__main__':
    server(8001)

客户端

# /usr/bin/env python3
# -*- encoding:utf-8 -*-

import socket

HOST = 'localhost'
PORT = 8001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
    msg = bytes(input(">>:"), encoding="utf8")
    s.sendall(msg)
    data = s.recv(1024)
    print('Received:',data.decode('utf-8'))

试着启动了一个服务端,多个客户端,与多个客户端的交互确实可以并行。但是服务端那里,只是生成了 greenlet 对象(gevent.spawn(handle_request, cli)),并没有 join 或 joinall,为什么也可以启动 spawn 生成的协程?

我又试着把第一个爬取网页的例子,去掉了 joinall ,像这样:

# /usr/bin/env python3
# -*- encoding:utf-8 -*-

# 第一个例子去掉 joinall ,结果并不执行

from gevent import monkey; monkey.patch_all()
import gevent,urllib.request

def f(url):
    print('GET: %s' % url)
    resp = urllib.request.urlopen(url)
    data = resp.read()
    print('%d bytes received from %s.' % (len(data), url))


gevent.spawn(f, 'https://www.python.org/')
gevent.spawn(f, 'https://www.yahoo.com/')
gevent.spawn(f, 'https://github.com/')

仅仅是 spawn 了3个协程对象,果然就不执行了,不解啊,为什么第一个爬取网页的例子没有 joinall 就不行,而第二个socket服务器的例子就不需要 joinall 啊

解决方案

因为它在一个 while True 里,永远也不会退出(就算是想 join 都没机会)。

顾名思义,spawn 就是启动了。join 只是等待它们结束而已。你不想等也是可以的,但是你直接退出的话它们也就都死掉了。

这篇关于python - gevent 模块生成的 greenlet 对象,要如何启动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆