2011-07-14 6 views
2

私は外部HTTPサービスを呼び出すPythonコードを持っています。これらの外部サービスを模倣する模擬HTTPサーバーを設定することによって、このコードをテストしたいと思います。別のスレッドでBaseHTTPServerを起動し、メインスレッドからそのサーバーを呼び出すことでこれを行います。それは次のようになります。Python BaseHTTPServerでランダムな読み取りエラーが発生するのはなぜですか?

import BaseHTTPServer, httplib, threading, time 

class MockHandler(BaseHTTPServer.BaseHTTPRequestHandler): 
    def do_POST(self): 
     self.send_response(200) 
     self.send_header('Content-Type', 'application/json') 
     self.end_headers() 
     self.wfile.write('{"result": "success"}') 

class ServerThread(threading.Thread): 
    def run(self): 
     svr = BaseHTTPServer.HTTPServer(('127.0.0.1', 8540), MockHandler) 
     svr.handle_request() 

ServerThread().start() 
time.sleep(0.1)    # Give the thread some time to get up 

conn = httplib.HTTPConnection('127.0.0.1', 8540) 
conn.request('POST', '/', 'foo=bar&baz=qux') 
resp_body = conn.getresponse().read() 

しかし、要求の一部はsocket.error: [Errno 104] Connection reset by peerと、read()呼び出しに失敗します。 Python 2.6のいくつかのマシンでは周波数を変えて再現できますが、2.7ではできません。

しかし、私がPOSTデータを送信しないと(つまり、3番目の引数をconn.request()にしないと)、エラーは発生しません。

これは何ですか?

また、模擬HTTPサーバーをPythonでセットアップするもう1つの方法がありますか?

答えて

1

"...別のスレッドで、メインスレッドからそのサーバーを呼び出しています。"

この種のスレッドにスレッドを使用しないでください。

プロセスを使用します。 subprocess.Popen(お使いのオペレーティングシステムの通常の機能)は、これが適切に動作することを保証するためにはるかに優れた仕事をします。

+0

なぜですか?スレッドがここで合理的であるように私には思われる... –

+1

@David Wolever:そうではありません。スレッドは多くのI/Oリソースを共有します。あるスレッドが読み込みを待っているときに、他のスレッドが必ずスケジュールされるとは限らず、HTTPライブラリーはピア状態メッセージによる奇妙な接続のリセットを提供します。プロセスは何も共有しないため、I/OはOSレベルのスケジューリングの考慮事項だけを進めることができます。スレッドは、I/Oの処理ではなく、計算集中型の処理にのみ使用する必要があります。これは明らかにI/O集約的です。 –

+0

ありがとうございます。私は 'Queue'を使ってサーバのリクエストをテストケースに返す'マルチプロセッシング 'の周りにモックサーバを書き直しました。これはうまく動作し、 'threading'と同じくらい簡単です。しかし、私はこの問題の原因を理解していないことを認めなければならない。さらに、Pythonのスレッドは、GILのために計算集約型のタスクでは役に立たないと信じていました。これは、あなたが言うことの反対です。私はいくつかの明るい文書を読む必要があると思う。 –

関連する問題