3

このコードのどこが間違っているか知っている人はいますか? それは単に永久に「ロード」されます。出力なし。「Sites」は、数十個の文字列のリストです。

num_worker_threads = 30

def mwRegisterWorker():
    while True:
        try:
            print q.get()
        finally:
            pass

q = multiprocessing.JoinableQueue()
for i in range(num_worker_threads):
     gevent.spawn(mwRegisterWorker)

for site in sites:
    q.put(site)

q.join()  # block until all tasks are done
4

2 に答える 2

11

gevent.spawn()プロセスではなくグリーンレットを作成します(さらに:すべてのグリーンレットは単一のOSスレッドで実行されます)。したがってmultiprocessing.JoinableQueue、ここでは適切ではありません。

gevent協調マルチタスクに基づいています。つまり、geventのイベントループに切り替わるブロッキング関数を呼び出すまで、他のグリーンレットは実行されません。たとえば、conn以下では、他のグリーンレットがサイトからの応答を待っている間に実行できるようにするgeventソケットメソッドのパッチを使用しています。そしてそれがなけれpool.join()ば、イベントループを実行するグ​​リーンレットへの制御を放棄し、接続は確立されません。

複数のサイトにリクエストを送信する際の同時実行を制限するには、次を使用できますgevent.pool.Pool

#!/usr/bin/env python
from gevent.pool import Pool
from gevent import monkey; monkey.patch_socket()
import httplib # now it can be used from multiple greenlets

import logging
info = logging.getLogger().info

def process(site):
    """Make HEAD request to the `site`."""
    conn = httplib.HTTPConnection(site)
    try:
        conn.request("HEAD", "/")
        res = conn.getresponse()
    except IOError, e:
        info("error %s reason: %s" % (site, e))
    else:
        info("%s %s %s" % (site, res.status, res.reason))
    finally:
        conn.close()

def main():
    logging.basicConfig(level=logging.INFO, format="%(asctime)s %(msg)s")

    num_worker_threads = 2
    pool = Pool(num_worker_threads)    
    sites = ["google.com", "bing.com", "duckduckgo.com", "stackoverflow.com"]*3
    for site in sites:
        pool.apply_async(process, args=(site,))
    pool.join()

if __name__=="__main__":
   main()
于 2011-09-25T19:17:12.063 に答える
3

gevent.queue.JoinableQueue代わりに使用してください。グリーン スレッド (gevent内部で使用) は、スレッドでもプロセスでもありませんが、ユーザー レベルのスケジューリングを伴うコルーチンです。

于 2011-09-25T20:39:02.027 に答える