2

私は、バックグラウンドタスクを起動し、それから進行を得ることができるはずの単純なブラウザベースのフロントエンドを書いています。タスクが正常に起動したかどうかを示す応答をブラウザが受信し、ポーリングしていつ実行されたかを判断する必要があります。ただし、バックグラウンドタスクが存在するため、XMLHttpRequest応答がすぐに送信されないようであるため、プロセスの起動の成功を報告できません。次の(簡略化された)コードについて考えてみます。

import SocketServer
import SimpleHTTPServer
import multiprocessing
import time

class MyProc(multiprocessing.Process):
    def run(self):
        print 'Starting long process..'
        for i in range(100): time.sleep(1)
        print 'Done long process'

class Page(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            print >>self.wfile, "<html><body><a href='/run'>Run</a></body></html>"
        if self.path == '/run':
            self.proc = MyProc()
            print 'Starting..'
            self.proc.start()
            print 'After start.'
            print >>self.wfile, "Process started."

httpd = SocketServer.TCPServer(('', 8000), Page)
httpd.serve_forever()

これを実行してhttp:// localhost:8000にアクセスすると、「実行」という名前のボタンが表示されます。それをクリックすると、ターミナルに次のように表示されます。

Starting..
After start.

ただし、ブラウザの表示は変わりません。実際、カーソルは回転しています。ターミナルでCtrl-Cを押してプログラムを中断した場合にのみ、ブラウザは次のメッセージで更新されます。Process started.

メッセージAfter startははっきりと印刷されています。do_GETしたがって、プロセスを開始した後、それが戻ってきていると推測できます。それでも、長時間実行されているプロセスを中断するまで、ブラウザーは応答を受け取りません。との間に何かがブロックされていると結論付ける必要があります。do_GETこれは、内部にありSimpleHTTPServerます。

スレッドとsubprocess.Popenでもこれを試しましたが、同様の問題が発生しました。何か案は?

4

3 に答える 3

3

スティーブと上記の私のコメントに加えて、ここに私のために働く解決策があります。

コンテンツの長さを決定する方法は少し醜いです。指定しない場合、コンテンツは表示されますが、ブラウザに回転するカーソルが表示される場合があります。self.wfile代わりに閉じることも機能する可能性があります。

from cStringIO import StringIO

class Page(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_GET(self):
        out = StringIO()
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        if self.path == '/':
            out.write("<html><body><a href='/run'>Run</a></body></html>\n")
        elif self.path == '/run':
            self.proc = MyProc()
            print 'Starting..'
            self.proc.start()
            print 'After start.'
            out.write("<html><body><h1>Process started</h1></body></html>\n")
        text = out.getvalue()
        self.send_header("Content-Length", str(len(text)))
        self.end_headers()
        self.wfile.write(text)
于 2010-10-20T15:45:55.783 に答える
2

このスニペットを使用して、SimpleHTTPServerのスレッドバージョンを実行します。

ThreadedHTTPServer.pyたとえば、このファイルを保存してから、次のように実行します。

$ python -m /path/to/ThreadedHTTPServer PORT

そのため、別々のスレッドで脅威にさらされ、並列でダウンロードして適切にナビゲートできるようになります。

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import threading
import SimpleHTTPServer
import sys

PORT = int(sys.argv[1])

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""

if __name__ == '__main__':
    server = ThreadedHTTPServer(('0.0.0.0', PORT), Handler)
    print 'Starting server, use <Ctrl-C> to stop'
    server.serve_forever()
于 2013-02-06T13:11:49.833 に答える
0

答えは、マルチプロセッシングモジュールが独自のstdoutを使用して完全に異なるプロセスをフォークすることです...したがって、アプリケーションは、記述したとおりに実行されます。

  1. ターミナルウィンドウでアプリケーションを起動します。
  2. /runでGETを実行するブラウザの[実行]ボタンをクリックします
  3. 現在のプロセスの出力がターミナルウィンドウ「Starting..」に表示されます。
  4. 新しいプロセス、独自のstdoutとstderrを備えたMyProcが開始されます。
  5. MyProcは、そのstdout(どこにも行かない)に「長いプロセスを開始しています..」と出力します。
  6. MyProcが起動した瞬間に、アプリは「起動後」というstdoutに出力されます。MyProcからの応答を待つように言われなかったからです。

必要なのは、メインアプリケーションのプロセスとフォークされたプロセスの間でやり取りするキューを実装することです。これを行う方法については、マルチプロセッシング固有の例がいくつかあります。

http://www.ibm.com/developerworks/aix/library/au-multiprocessing/

ただし、その記事(IBMのほとんどの記事と同様)は、一種の深く複雑です...「通常の」キューモジュールの使用方法のより簡単な例を見てみることをお勧めします(これは、マルチプロセッシングに含まれるもの):

http://www.artfulcode.net/articles/multi-threading-python/

理解しておくべき最も重要な概念は、キューを使用してプロセス間でデータをシャッフルする方法と、join()を使用して応答を待ってから続行する方法です。

于 2010-10-20T02:15:06.390 に答える