2009-08-29 7 views
4

アップロードされたファイルを使ってさまざまな長い計算を行うDjangoアプリケーションを作成しています。私は、ユーザーがファイルが処理されるのを待つようにしたくありません - 私はちょうど 'ファイルが解析されている'のようなものを読んでいるページをユーザーに見せたいだけです。Python [Django]から非同期関数呼び出しを行う方法はありますか?

ビューから非同期関数呼び出しを作成するにはどうすればよいですか?

そのように見えるかもしれません何か:

def view(request): 
    ... 
    if form.is_valid(): 
     form.save() 
     async_call(handle_file) 
    return render_to_response(...) 
+0

重複の新機能:http://stackoverflow.com/questions/546017/how-do-i- Pythonを実行して別のスクリプトを実行するのを待つことなく、http://stackoverflow.com/questions/1081340/how-do-you-do-something-after-you-render- the-view-django –

+0

もっと類似している:http://stackoverflow.com/questions/1239035/asynchronous-method-call-in-python –

答えて

7

これを管理するのではなく、サブプロセスまたはスレッドで管理するのではなく、完全に分離することをお勧めします。最初は、データベーステーブルのどこかにフラグを設定し、フラグをチェックして必要な操作を実行するcronジョブを定期的に実行する方法が2つあります。

2番目のオプションは、メッセージキューを使用することです。ファイルのアップロードプロセスでキューにメッセージが送信され、別のリスナーがメッセージを受信して​​必要な処理を行います。私はRabbitMQをこの種のものに使用しましたが、他のものは利用可能です。

いずれの場合でも、ユーザーはプロセスが終了するのを待つ必要はなく、サブプロセスの管理について心配する必要はありません。

+0

ああ、どうして私はこれを考えなかったのですか?ありがとう、それは本当に良い点です。私はほとんどcronを忘れていました。ありがとう、それは問題をきちんと解決するはずです:) – DataGreed

+0

問題は、cron(と簡単なcronのように動作するデバッグマシン上の単純なshedule pythonスクリプト:)によって解決されます。) – DataGreed

+1

somoneが解決策を今読んでいる場合、私はセロリーを試してみることをお勧めします。 – DataGreed

0

あなたは、具体的S.Lottがあなたの重複として表示している他の質問の主旨であるように思われ、別のプロセスを使用する必要がない限り、threadingモジュールは、Python標準ライブラリ(hereと記載されています)から、最も簡単な解決策を提供します。 handle_fileが変更される可能性のあるグローバルにアクセスしていないことを確認してください。特に、グローバル自体を変更することは特にありません。理想的にはそれはあなたのプロセスの残りの部分とQueueインスタンスを介してのみ通信する必要があります。等、スレッド化に関するすべての通常の推奨;-)。

+1

あなたの答えをありがとう。私はそれを理解していますか?主なアプリケーションのメインは、いくつかのファイル処理を伴うスレッドがまだ実行中であっても終了しますか?または、スレッドも終了されますか?そうであれば、多くのウェブサーバーが必要なときにmanage.pyプロセスを生成し、ビジー状態でないものが多すぎるとそれらを殺すので、役に立たないものです。 私は現在、os.system( 'python handle_file.py path/to/file')のようなものを追加しています... – DataGreed

+0

はまだサブプロセスになっていると思っています。 subprocess.Popenを使用する必要があります。 – DataGreed

+0

サブプロセスが必要な場合は、サブプロセスが必要です.Slottが正しいとします(その人が私の担当者のほぼ2倍の理由があると推測します;-))。しかし、完全性のために、最後のNON-DAEMONスレッドが終了する前に終了すると、Pythonプロセスは「自然に」終了します。そのため、ジョブを終了するために重要なスレッドは、デーモン(デフォルト)または明示的にプロセス終了時のメインスレッドに参加する必要があります。バックグラウンドタスクを実行する "ワーカースレッド"はデーモンでなければなりません(.join ' dに;-)それらが無害に終わるかもしれないならば。 –

2

私は同じことをやろうとしていますが、djangoやその他の非同期呼び出しの性質のために、複数の試行の後に失敗しました。

私はあなたのためにトップを少し上にする可能性がある解決策は、バックグラウンドで別の非同期サーバーをWeb要求からのメッセージキューを処理し、ブラウザのブラウザから直接解析されるいくつかのチャンクされたjavascriptを投げることです非同期の方法(すなわち:ajax)。

mod_proxy設定ですべてのことがエンドユーザーにとって透過的になります。

+0

アイデアありがとう、しかし、私はちょうど2番目のサーバーを実行するためにプロジェクトが巨大で公共ではないので、キューのすべてのファイルを解析するmanage.pyコマンドを開始するためにcronを使用する必要がありますね:) – DataGreed

0

私が間違っていないと、スレッドはrunserverを破ります。私は、mod_wsgiとrunserverを持つリクエストハンドラでマルチプロセスに腹を立てました。たぶん誰かが、これは不良である理由として、私を啓発することができます。

def _bulk_action(action, objs): 
    # mean ponies here 

def bulk_action(request, t): 

    ... 
    objs = model.objects.filter(pk__in=pks) 

    if request.method == 'POST': 
     objs.update(is_processing=True) 

     from multiprocessing import Process 
     p = Process(target=_bulk_action,args=(action,objs)) 
     p.start() 

     return HttpResponseRedirect(next_url) 

    context = {'t': t, 'action': action, 'objs': objs, 'model': model} 
    return render_to_response(...) 

http://docs.python.org/library/multiprocessing.html

を2.6

+0

私は、分離されたプロセスに参加するためにどこかにp.join()を持つ必要があると思います:) –

関連する問題