1

検証するURLが100万あります。それらのいくつかは私の国から到達不能であり、いくつかは無効です、私はすべての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個のURLを持っているかどうかを知っています、私は次のようなgeventを使用できます:

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

しかし、私の状況では、1つのメッセージを読んでからグリーンレットを生成し、URLに到達できない場合は、グリーンレットが終了するまでメッセージをブロックします。

では、URLを検証するための非同期の方法をどのように行うことができますか?たとえば、私は常にURLを読み返し、ブロックせずにグリーンレットを生成します。

どうも

4

1 に答える 1

2

IO/「待機中」コードを でラップする必要があります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()コンテキストでラップする必要があります。

また、タイムアウトをチェックするだけであれば、これで問題ありません。200ただし、リクエストが HTTP コードを返したかどうかを確認したい場合があります。その場合は、 urllib2.urlopen(url).getcode().

于 2013-03-19T02:51:10.253 に答える