我有一百万个网址需要验证。 其中一些是无法访问我的国家,有些是无效的,我想验证所有的网址。 我使用python来做到这一点,并使用gevent来加快速度,但我是gevent的新手,有些似乎没有用。 我的代码如下:
import gevent
import gevent.monkey
import urllib2
from gevent.pool import Pool
from gevent import Timeout
gevent.monkey.patch_all()
p = Pool(10)
seconds = 10
#timeout = Timeout(seconds)
#timeout.start()
#timer = Timeout(3).start()
def down(url):
urllib2.urlopen(url)
def wait():
while True:
gevent.sleep(0)
print 'hi'
with Timeout(5,False):
p.spawn(down,'http://www.twitter.com')
print '---------------------------------'
wait()
我的国家无法访问Twitter,输出是:
hi
---------------------------------
hi
---------------------------------
hi
并且它在5秒后没有告诉超时,我的代码出了什么问题?
我想知道如何在运行时为gevent添加新任务。
我想在分发中验证我的所有网址,所以我从我的数据库中读取网址并将网址发送到消息队列,很多接收方从消息中接收消息,然后验证网址。
我的信息是rabbitmq。
我只知道如果我有10个网址,我可以使用gevent:
for x in xrange(10)
tasks.append(gevent.spawn(validate,url))
gevent.joinall(tasks)
但在我的情况下,我只读了一条消息然后产生一个greenlet,如果一个url无法访问,它将阻止该消息,直到greenlet完成。
那我该如何做一些异步方式来验证我的网址呢? 比如我总是把网址读回来并且不会阻塞地生成greenlet。
THX
答案 0 :(得分:2)
您需要使用with Timeout()
包装IO /“等待”代码。现在,你正在包裹gevent.spawn()
/ pool.spawn()
来电,这是不对的。在这种情况下,要暂停的IO代码为urllib2.urlopen(url)
。
这种性质的代码通常看起来像这样:
validated = []
urls = ["http://a.com", "http://b.com"]
def down(url):
with Timeout(5, False):
urllib2.urlopen(url)
validated.append(url)
pool = gevent.Pool(10)
for url in urls:
pool.spawn(down, url)
pool.join() #you didn't call pool.join() in the original code because you have a wait loop already, which is okay
print "Valid URLs are: %s" % ", ".join(validated)
您可以保留无限while True
循环,并从中获取数据库/队列中的传入URL。这可能就是你想要的。我只是举例说明如何检查我要验证的预设URL列表。
在这种情况下,您的错误是您使用pool.spawn()
包裹with Timeout()
。刚生成greenlet的行为几乎会立即发生,所以在此周围添加一个超时将无能为力。这就是为什么你没有看到超时。您需要使用urllib2.urlopen()
上下文打包Timeout()
。
此外,如果你只是检查超时,这很好。您可能想要检查请求是否返回了HTTP 200
代码,在这种情况下,您应该检查urllib2.urlopen(url).getcode()
。