1

リクエストハンドラーでsubprocess.Popenによって新しいプロセスが生成された場合、SimpleHTTPRequestHandlerでのリクエストの戻りがブロックされるという奇妙な問題があります。しかし、Popen は非同期であるべきではありませんか?

この動作は、次のファイルによって再現可能であり、私の OS X マシンでは Python 2.6.7 を使用し、SLES マシンでは ActivePython 2.6 を使用します: webserver.py:

#!/usr/bin/env python
import SimpleHTTPServer
import SocketServer
import subprocess
import uuid

class MyRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_POST(self):
        print 'in do_POST'
        uuid_gen = str(uuid.uuid1())
        subprocess.Popen(['python', 'sleep.py'])
        print 'subprocess spawned'
        return self.wfile.write(uuid_gen)

Handler = MyRequestHandler

server = SocketServer.TCPServer(('127.0.0.1', 9019), Handler)

server.serve_forever()

sleep.py:

import time
time.sleep(10)

Web サーバーを起動してから、localhost:9019 に対して curl POST リクエストを実行すると、Web サーバーは即座に次のように出力します。

$python2.6 webserver2.py
in do_POST
subprocess spawned

しかし、curl リクエストを実行するコンソールでは、次の動作が示されます。

$curl -X POST http://127.0.0.1:9019/
<wait ~10 seconds>
cd8ee24a-0ad7-11e3-a361-34159e02ccec

Python 2.7 で同じセットアップを実行すると、curl サイトにすぐに答えが届きます。Popen は印刷をブロックしていないように見えますが、リターンだけをブロックしているように見えるので、これはどのように起こりますか? 問題は、レガシーの理由で python 2.6 にバインドされていることです。そのため、リクエストを即座に返すための最善の回避策は何でしょうか?

4

1 に答える 1

0

わかりましたので、Nikhil がこの質問https://stackoverflow.com/questions/3973789/...を参照した後、私は self.send_response(200), self.send_header("Content-Length", str( len(uuid_gen))) と self.end_headers()。

これは、作業コードが次のようになることを意味します。

#!/usr/bin/env python
import SimpleHTTPServer
import SocketServer
import subprocess
import uuid

class MyRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_POST(self):
        print 'in do_POST'
        uuid_gen = str(uuid.uuid1())
        subprocess.Popen(['python', 'sleep.py'])
        print 'subprocess spawned'
        self.send_response(200)
        self.send_header("Content-Length", str(len(uuid_gen)))
        self.end_headers()
        self.wfile.write(uuid_gen)

Handler = MyRequestHandler

server = SocketServer.TCPServer(('127.0.0.1', 9019), Handler)

server.serve_forever()

Popen プロセスが終了したときに正確に戻る理由はまだよくわかりませんが、問題はパイプライン用に HTTP 接続が開いたままになっているようです。

于 2013-08-22T04:01:12.590 に答える