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 啊
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
因为它在一个 while True 里,永远也不会退出(就算是想 join 都没机会)。
顾名思义,spawn 就是启动了。join 只是等待它们结束而已。你不想等也是可以的,但是你直接退出的话它们也就都死掉了。
我猜是因为accept()执行的时候让出了CPU吧。