子进程
从 gevent 1.0 开始,已经添加了 gevent.subprocess——Python 的 subprocess 模块的修补版本。 它支持对子进程的协作等待。
# 中间插入子进程
import gevent
from gevent.subprocess import Popen, PIPE
def cron():
while True:
print("cron")
gevent.sleep(0.2)
g = gevent.spawn(cron)
sub = Popen(['sleep 1; uname'], stdout=PIPE, shell=True)
out, err = sub.communicate()
g.kill()
print(out.rstrip())
'''
cron
cron
cron
cron
cron
Linux
'''
许多人还希望将 gevent 和 multiprocessing 一起使用。 最明显的挑战之一是多处理提供的进程间通信在默认情况下是不合作的。 由于基于 multiprocessing.Connection 的对象(例如 Pipe)公开了它们的底层文件描述符,因此 gevent.socket.wait_read 和 wait_write 可用于在实际读取/写入之前协同等待准备读取/准备写入事件:
import gevent
from multiprocessing import Process, Pipe
from gevent.socket import wait_read, wait_write
# To Process
a, b = Pipe()
# From Process
c, d = Pipe()
def relay():
for i in xrange(10):
msg = b.recv()
c.send(msg + " in " + str(i))
def put_msg():
for i in xrange(10):
wait_write(a.fileno())
a.send('hi')
def get_msg():
for i in xrange(10):
wait_read(d.fileno())
print(d.recv())
if __name__ == '__main__':
proc = Process(target=relay)
proc.start()
g1 = gevent.spawn(get_msg)
g2 = gevent.spawn(put_msg)
gevent.joinall([g1, g2], timeout=1)
但是请注意,多处理和 gevent 的组合带来了某些依赖于操作系统的陷阱,其中包括:
在符合 POSIX 的系统上分叉后,孩子的 gevent 状态是不适定的。一个副作用是 greenlets 在 multiprocessing.Process 创建之前产生,在父进程和子进程中运行。
上面 put_msg() 中的 a.send() 可能仍会以非合作方式阻塞调用线程:准备写入事件仅确保可以写入一个字节。在尝试写入完成之前,底层缓冲区可能已满。
上述基于 wait_write() / wait_read() 的方法在 Windows 上不起作用(IOError: 3 is not a socket (file is not supported)),因为 Windows 无法监视事件管道。
Python 包 gipc 在符合 POSIX 的系统和 Windows 系统上以一种非常透明的方式为您克服了这些挑战。它提供了 gevent-aware multiprocessing.Process-based child processes 和基于管道的 gevent-cooperative 进程间通信。