8


6

私はPythonとスレッドで少し遊んだばかりで、マルチスレッドスクリプトでもDNS要求がブロックされていることに気付きました。 次のようなスクリプトを考えます。

スレッドインポートからスレッドインポートソケット

Connection(Thread)クラス:def __init __(self、name、url):スレッド.__ init __(self)

def run(self):「接続しています...」を印刷し、self._nameを試してください。 socket.gaierrorを除いて:それに興味を持っていません# "print"、 "self._name"を渡してください

if __name__ == '__main__':conns = []#それらがどのように失敗/チェックするのかを見るためにすべての無効なアドレスconns.append(Connection( "conn1"、 "www.2eg11erdhrtj.com"))conns.append(Connection( " conn2 "、" www.e2ger2dh2rtj.com "))conns.append(接続(" conn3 "、" www.eg2de3rh1rtj.com "))conns.append(接続(" conn4 "、" www.ege2rh4rd1tj.com ")) conns.append(Connection( "conn5"、 "www.ege52drhrtj1.com"))

conn内のconnの場合:conn.start()

タイムアウトの長さは正確にはわかりませんが、これを実行すると次のようになります。

  1. すべてのスレッドが起動し、印刷物が表示されます

  2. xx秒ごとに、一度に全部ではなく1つのスレッドが終了表示されます。

  3. スレッドは一度に全部ではなく、順番に終了します(timeout =すべての人で同じです)

だから私の唯一の推測はこれがGILと関係があるということでしょうか? 明らかに、スレッドはそれらのタスクを同時に実行するのではなく、一度に1つの接続しか試みられません。

誰もがこれを回避する方法を知っていますか?

(* asyncore は助けにはならない、そして今のところ twisted *は使わない方がいい)pythonでこの簡単なことをさせるのは不可能だろうか?

ご挨拶、トム

編集:

私はMacOSXを使っています、私は私の友人にLinuxでこれを実行させるだけです、そして彼は実際に私が得たいと思った結果を得ます。 彼のsocket.connects()は、スレッド化されていない環境であっても即座に戻ります。 そして、彼がソケットをブロックに設定し、10秒にタイムアウトしても、彼のすべてのスレッドは同時に終了します。

誰もがこれを説明できますか?

3 Answer


15


システムによっては、getaddrinfoはスレッドセーフではありません。 Pythonは、そのようなシステムの中にはFreeBSD、OpenBSD、NetBSD、OSX、そしてVMSがあると考えています。 これらのシステムでは、Pythonはnetdb(つまり、netdb)専用のロックを維持しています。 getaddrinfoとその友達)

そのため、オペレーティングシステムを切り替えることができない場合は、twistedのような別の(スレッドセーフな)リゾルバライブラリを使用する必要があります。


2


それが適切ならば、プロセスベースの並列処理を可能にするために `multiprocessing`モジュールを使うことができます

import multiprocessing, socket

NUM_PROCESSES = 5

def get_url(url):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setblocking(0)
        s.connect((url, 80))
    except socket.gaierror:
        pass #not interested in it
    return 'finished ' + url


def main(url_list):
    pool = multiprocessing.Pool( NUM_PROCESSES )
    for output in pool.imap_unordered(get_url, url_list):
        print output

if __name__=="__main__":
    main("""
             www.2eg11erdhrtj.com
             www.e2ger2dh2rtj.com
             www.eg2de3rh1rtj.com
             www.ege2rh4rd1tj.com
             www.ege52drhrtj1.com
          """.split())


1


http://twistedmatrix.com/trac/wiki/TwistedNames[ツイスト名]を使用して、DNS要求を非同期的に送信します。
twisted.internetからsysをインポートします。twisted.internetからインポートリアクタをインポートします。

def process_names(names):log.startLogging(sys.stderr、setStdout = False)

def print_results(results):名前は、(success、result)、zip(names、results)は、成功した場合:print "%s  - >%s"%(name、result)それ以外の場合:print >> sys.stderrエラー:%sが失敗しました。 理由:%s "%(名前、結果)

d = defer.DeferredList(map(client.getHostByName、names)、consumeErrors = True)

reactor.callWhenRunning(プロセス名、 "" "google.com www.2eg11erdhrtj.com www.e2ger2dh2rtj.com www.eg2de3rh1rtj.com www.ege2rh4rd1tj.com www.ege52drhrtj1.com" ".split()