1

我有一百万个要验证的网址。其中一些是我的国家无法访问的,有些是无效的,我想验证所有的 url。我使用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()

推特无法从我的国家/地区访问,输出为:

hi
---------------------------------
hi
---------------------------------
hi

5秒后它没有告诉超时,我的代码有什么问题?

我想知道如何在运行时向 gevent 添加新任务。

我想在分发中验证我的所有 url,所以我从我的数据库中读取 url 并将 url 发送到消息队列,很多接收者从消息中接收消息,然后验证 url。

我的消息是rabbitmq。

我只知道我是否有 10 个网址,我可以使用 gevent,例如:

for x in xrange(10)
    tasks.append(gevent.spawn(validate,url))
gevent.joinall(tasks)

但在我的情况下,我只阅读了一条消息,然后生成了一个 greenlet,如果一个 url 无法访问,它将阻止该消息,直到 greenlet 完成。

那么我怎样才能做一些异步的方式来验证我的网址呢?比如我总是读回 url 并在没有阻塞的情况下生成 greenlet。

谢谢

4

1 回答 1

2

您需要用with Timeout(). 现在,您正在包装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()

此外,如果您只是检查超时,这很好用。您可能想要检查请求是否返回了 HTTP200代码,在这种情况下,您应该检查urllib2.urlopen(url).getcode().

于 2013-03-19T02:51:10.253 回答