2016-05-18 10 views
1

私は基本的にPythonスクリプトのブラウザインタフェースとして機能するweb2pyアプリケーションを持っています。このスクリプトは通常かなり早く戻りますが、時には時間がかかることがあります。スクリプトの実行が長時間かかると、ユーザーがそのスクリプトの実行を停止する方法を提供したいと考えています。マルチプロセスでweb2pyで長時間実行されるアクションを停止する

は、私は現在、このような関数を呼び出しています:特定のオプションと呼ばれる

def myView(): # this function is called from ajax 
    session.model = myFunc() # myFunc is from a module which i have complete control over 
    return dict(model=session.model) 

myFuncは、マルチプロセッシングを使用していますが、まだ長い時間がかかってしまいます。私は、関数を終了するために、または少なくともスレッドの子プロセスを終了させるための何らかの方法が必要です。

私が試した最初のものは、新しいプロセスでmyFuncを実行し、それを殺すために自分の単純なイベントシステムをロールすることでした:

# in the controller 
def myView(): 
    p_conn, c_conn = multiprocessing.Pipe() 
    events = multiprocessing.Manager().dict() 
    proc = multiprocessing.Process(target=_fit, args=(options, events c_conn)) 
    proc.start() 
    sleep(0.01) 
    session.events = events 
    proc.join() 
    session.model = p_conn.recv() 
    return dict(model=session.model) 

def _fit(options, events pipe): 
    pipe.send(fitting.logistic_fit(options=options, events=events)) 
    pipe.close() 

def stop(): 
    try: 
     session.events['kill']() 
    except SystemExit: 
     pass # because it raises that error intentionally 
    return dict() 

# in the module 
def kill(): 
    print multiprocessing.active_children() 
    for p in multiprocessing.active_children(): 
     p.terminate() 
    raise SystemExit 

def myFunc(options, events): 
    events['kill'] = kill 

私はこれでいくつかの主要な問題に遭遇しました。

  1. stop()でのセッションはとてもsession.eventsなしではなかった、myView()に常にセッションと同じではありませんでした。
  2. セッションが同じであっても、kill()は子を正しく殺していませんでした。
  3. 長時間実行される関数はweb2pyスレッドをハングするので、関数が終了するまでstop()は処理されませんでした。

私はjoin()を呼び出して、後で関数の結果を拾うためにAJAXを使用していないと考えるが、私は後で使用するためにsessionのプロセスオブジェクトを保存することができませんでした。パイプは節約できると思われましたが、別のビューから同じセッションにアクセスできないという問題がありました。

この機能はどのように実装できますか?

答えて

1

長時間実行するタスクの場合は、組み込みのschedulerを使用してキューイングする方がよい場合があります。ユーザーが手動で長時間かかるタスクを停止できるようにする場合は、scheduler.stop_task(ref)メソッド(refは、タスクidまたはuuid)を使用できます。また、タスクをキューイングするときにタイムアウトを指定することもできます。タイムアウト時間内に完了しないと自動的に停止します。

単純なAjaxポーリングを実行して、タスクが完了したときにクライアントに通知したり、WebソケットやSSEでより洗練されたものを実装したりすることができます。

+0

あなたは答えにお答えください。答えに値するいくつかの具体的な事柄:スケジューラーはスクリプトからすぐにタスクを開始しますか?どのようにタスクの結果を得るには?どのように強制的にタスクを停止する?そうであるように、これは完全に質問に答えるものではありません。 – Scimonster

+0

あなたの最後の質問に答える答えを更新しました。あなたの最初の2つの質問は、リンクされたドキュメントに記載されています。それらは一般的なスケジューラー機能を含み、元の質問の一部ではないので、私は答えを更新しませんが、デフォルトでは新しいタスクがすぐにキューに入れられることを簡単に言及します(そして、 'immediate = True')、' scheduler.task_status() 'メソッドを使用して結果を取得します。 – Anthony

関連する問題