Pythonライブラリの不具合かどうか

先日、ここでPython Webスパイダーを作成しました。タスクは一般に単純ですが、負荷が大きいため、実際には5つのスパイダー(5つのスレッド)を実行する必要があります。一般的に、ソリューションは興味深いものでした。標準のPython libs socket



httplib



urllib2



に登る機会がありurllib2



(興味があれば、この経験を説明できます)。







ここでお話ししたいのは、作成されたオブジェクトに従わないという中毒が、ガベージコレクション言語で教えられることです。 スパイダーを監視しているときに、 CLOSE_WAIT



状態の多くのソケットがシステムにハングしていることに気付きました。 これは、サーバー側でソケットが既に閉じられているが、まだメモリに残っているためです。 つまり、大まかに言って、 close



メソッドはソケットで呼び出されず、オブジェクト自体はまだメモリのどこかにハングしています。



urllib2、 urllib2



、およびsocket



を調べたurllib2



、それらの作業のメカニズムに関する次の情報を受け取りました。



  1. ページをロードするには、 urllib2.OpenDirector.open



    呼び出しurllib2.OpenDirector.open



  2. urllib2.HTTPHandler.open



    メソッドを呼び出し、 urllib2.HTTPHandler.open



    を呼び出しますurllib2.AbstractHTTPHandler.do_open



  3. 通信タスクを直接実行するために、 httplib.HTTPConnection



    にタイプdo_open



    h



    オブジェクトが作成されます。 重要なポイントdo_open



    を終了すると、このオブジェクトは消えます!
  4. h



    はソケットを生成して開き、 self.sock



    属性に保存します。
  5. h



    は、サーバーに要求を送信します。
  6. do_open



    はサーバーにh



    を要求し、タイプhttplib.HTTPResponse



    r



    オブジェクトをhttplib.HTTPResponse



    ます。
  7. このオブジェクトは、 h.sock



    ソケットに基づいて作成されると、アプリケーションがデータの読み取りに使用するh.sock.makefile



    メソッドを使用してh.sock.makefile



    ファイルオブジェクトを作成します。 繰り返しますが、重要な点は、コンストラクターに渡されるソケットオブジェクトはどこにも保存されないということです。
  8. do_open



    は、受信したHTTPResponse



    をサービスオブジェクトにラップし、アプリケーションに返します。
  9. アプリケーションはデータを読み取り、 HTTPResponse



    を閉じます。




したがって、ソケットオブジェクト自体(実際のソケットのラッパー)はもう存在しない可能性があります。 少なくともどこにもリンクがありません。 しかし、ソケット自体はまだ残っています! 誰も彼を近くに電話しませんでした! 要するに、これまでのところ、1つのオプションだけが思い浮かびました。読み取りが完了したら、次の形式の「わかりやすい」コードを使用して、サービスリンクのかかとを通してソケットを手動で閉じます。

 tf.fp._sock.fp._sock.close()


ここで、 tf



はurllib2.openから取得したリンクです。 これはパイです:)これは、2.5に戻ったところであります。 2.4では、さらに悪いバグがいくつかあります。 この振る舞いを正しく打ち破る方法についてのヒントを喜んでいます。



All Articles