gevent模块的使用中,如果“主线程”有非I/O的阻塞,会影响其他协程的执行?

gevent模块的使用中,如果“主线程”(这个表述不太准确)中,有非IO的阻塞操作(比如 input),就会让其他协程无法执行?

比如:

例子①

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

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, 'http://www.163.org/')
gevent.spawn(f, 'http://www.qq.com/')
gevent.spawn(f, 'http://www.baidu.com/')

while 1:
    msg = input('>> ').strip()
    print(msg)

或者 将 while 1: 中的代码换成 pass,协程都貌似不会执行的样子。

但是如果 将 while 1: 中的代码 换成 time.sleep(1) 这种,就可以执行了

这是,为什么???

如果我一定需要 “主线程” 中有 input 这种阻塞,该如何处理?

比如如下代码,用来获取url的主页长度。要求:
①在一个死循环中,input 接收输入

②如果输入 get + 域名,开启一个协程在后台处理获取url长度的操作,该操作不能阻塞 “主线程”,即:输入后,就可以立刻进行下一次输入,不等待

③如果输入 result + 域名,就返回 域名 对应url的主页长度(还没处理完就提示等待)

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

# 错误示例  

import urllib.request,gevent

res = {}

def get_url(url):
    resp = urllib.request.urlopen(url)
    res[dn] = len(resp.read())


while 1:
    cmd = input('>> ').strip()

    if cmd.startswith('get'):
        dn = cmd.split()[1]
        url = 'http://%s.com'%dn
        gevent.spawn(get_url,url)
        print('Start handling the request,plz wait a moment...')

    elif cmd.startswith('result'):
        dn = cmd.split()[1]
        if dn in res:
            print(res[dn])
            del res[dn]
        else:
            print('Request is handling...')
    else:
        print('Commad not found')

以上代码需如何修改,才能达到要求,我知道用多线程/多进程一定是可以的,如果就用gevent该如何实现呢?

阅读 4.6k
1 个回答

记得哪篇文档里提到了 gevent就不要有这种阻塞操作 本身不符合协程的意义

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题