学习gevent之基本用法
更新日期:
花了点时间学习gevent, 目前只了解其基本用法,但还不清楚实现原理。
一些学习资源:
- gevent site http://gevent.org/
- gevent in GitHub https://github.com/gevent/gevent
- Gevent Tutorial http://sdiehl.github.io/gevent-tutorial/
- Gevent Tutorial 中文翻译 http://xlambda.com/gevent-tutorial/
简单用法
下面的代码来自Gevent Tutorial. 首先定义两函数foo()和bar()来实现具体的操作,再由gevent.spawn()创建Greenlet对象来执行foo()/bar(),最后gevent.joinall()来等待两greenlet执行结束。foo()/bar()中调用gevent.sleep(0)来显式切换到不同的Greenlet。
1 | import gevent |
要点:
- 使用
gevent.spawn()或直接创建Greenlet来新建执行单元 join()函数来等待所有执行单元结束- 执行的函数里在需要等待时能切换到其它,比如
gevent.sleep(0), 或是网络等待事件 - Monkey patching打补丁来支持gevent, 如:
1 | from gevent import monkey; monkey.patch_socket() |
- 提供一些数据结构来支持Greenlet之间的通信,如
gevent.queue.Queue
使用gevent来实现并行查询数据
作为练习,实现的功能是手机号码归属地查询。代码仅为学习交流之用,故隐藏了查询所使用的url, 切勿用于其它目的,且本人不对使用产生的任何后果负责。
tasks = Queue()用于存放phone number,leadWorker()生成号码放在tasks中,queryWorker()从tasks中取出一个号码查询- 查询的结果放入
resultQue = Queue(),writeWorker()会读取该queue的内容然后写入文件 - 1个
leadWorker()和10个queryWorker()同时工作
1 | #!/usr/bin/env python |
后记
尽管添加了try-catch,但在获取1万个号码地区时还是遇到了一些问题。代码运行开始时设定的worker数是10个,但在接近完成一半时发现有些worker不打印log了:第一次结尾时有5个worker打印出完成,第二次时只有一个了。可能是有等待,两次都没有正常退出,只好ctrl+c强制结束了。这是一个问题,需要解决。
后来看到有错误Connection timed out。尽管有try-finally,但看样子是没catch住。
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/gevent/greenlet.py", line 327, in run
result = self._run(*self.args, **self.kwargs)
File "phn.py", line 29, in queryWorker
resp = urllib2.urlopen(req)
File "/usr/lib/python2.7/urllib2.py", line 127, in urlopen
return _opener.open(url, data, timeout)
File "/usr/lib/python2.7/urllib2.py", line 404, in open
response = self._open(req, data)
File "/usr/lib/python2.7/urllib2.py", line 422, in _open
'_open', req)
File "/usr/lib/python2.7/urllib2.py", line 382, in _call_chain
result = func(*args)
File "/usr/lib/python2.7/urllib2.py", line 1222, in https_open
return self.do_open(httplib.HTTPSConnection, req)
File "/usr/lib/python2.7/urllib2.py", line 1184, in do_open
raise URLError(err)
URLError:
failed with URLError