socket
、
httplib
、
urllib2
に登る機会があり
urllib2
(興味があれば、この経験を説明できます)。
ここでお話ししたいのは、作成されたオブジェクトに従わないという中毒が、ガベージコレクション言語で教えられることです。 スパイダーを監視しているときに、
CLOSE_WAIT
状態の多くのソケットがシステムにハングしていることに気付きました。 これは、サーバー側でソケットが既に閉じられているが、まだメモリに残っているためです。 つまり、大まかに言って、
close
メソッドはソケットで呼び出されず、オブジェクト自体はまだメモリのどこかにハングしています。
urllib2、
urllib2
、および
socket
を調べた
urllib2
、それらの作業のメカニズムに関する次の情報を受け取りました。
- ページをロードするには、
urllib2.OpenDirector.open
呼び出しurllib2.OpenDirector.open
。 -
urllib2.HTTPHandler.open
メソッドを呼び出し、urllib2.HTTPHandler.open
を呼び出しますurllib2.AbstractHTTPHandler.do_open
- 通信タスクを直接実行するために、
httplib.HTTPConnection
にタイプdo_open
のh
オブジェクトが作成されます。 重要なポイントdo_open
を終了すると、このオブジェクトは消えます! -
h
はソケットを生成して開き、self.sock
属性に保存します。 -
h
は、サーバーに要求を送信します。 -
do_open
はサーバーにh
を要求し、タイプhttplib.HTTPResponse
r
オブジェクトをhttplib.HTTPResponse
ます。 - このオブジェクトは、
h.sock
ソケットに基づいて作成されると、アプリケーションがデータの読み取りに使用するh.sock.makefile
メソッドを使用してh.sock.makefile
ファイルオブジェクトを作成します。 繰り返しますが、重要な点は、コンストラクターに渡されるソケットオブジェクトはどこにも保存されないということです。 -
do_open
は、受信したHTTPResponse
をサービスオブジェクトにラップし、アプリケーションに返します。 - アプリケーションはデータを読み取り、
HTTPResponse
を閉じます。
したがって、ソケットオブジェクト自体(実際のソケットのラッパー)はもう存在しない可能性があります。 少なくともどこにもリンクがありません。 しかし、ソケット自体はまだ残っています! 誰も彼を近くに電話しませんでした! 要するに、これまでのところ、1つのオプションだけが思い浮かびました。読み取りが完了したら、次の形式の「わかりやすい」コードを使用して、サービスリンクのかかとを通してソケットを手動で閉じます。
tf.fp._sock.fp._sock.close()
ここで、
tf
はurllib2.openから取得したリンクです。 これはパイです:)これは、2.5に戻ったところであります。 2.4では、さらに悪いバグがいくつかあります。 この振る舞いを正しく打ち破る方法についてのヒントを喜んでいます。