2012-11-08 29 views
5

私は基本的にユーザーにファイルを提供するPython + Tornadoを使用してWebアプリケーションを作成しています。私はデータベースがありません。関数へのTornado非同期呼び出し

ファイルは、使用可能な場合は直接ピックアップされ、提供されるか、そうでない場合は生成されます。

いくつかのファイルはすでに利用可能であるかもしれないが、他のファイルは生成される必要がある(したがって、彼らは待つ必要があり、他のユーザーをブロックしたくない)ので、クライアントを非同期で提供したい。

私はファイルのピッキングや生成を管理するクラスを持っています。私はそれをTornadoから呼び出すだけです。

これを達成する最も良い方法(CPUとRAMで最も効率的)は何ですか?スレッドを使うべきですか?サブプロセス?シンプルなgen.Task like this one

また、私の実装はGoogle App Engineで動作するようにしたいと思います(サブプロセスを生成することはできないと思います)。

私は非同期Webサービスに比較的新しいので、どんなヘルプも歓迎します。

+1

gen.Taskが正常に動作します。あなたのファイルを取得/生成しているコードがうまくいけば、スレッドは正常に動作します。複数のプロセスを起動することもできますが、Google App Engineの制限はわかりません。 – sean

+0

返事ありがとうございます。また、私は複数のgen.Taskを生成する場合、それがうまくいく方法を知っていますか?私の**インスタンスメソッド**はCPUと時間がかかることがあります。このメソッドが複数のユーザーから何回か呼び出されると、どうなりますか?すべてのメソッドが非同期に並行して実行されるのでしょうか、あるいは次のメソッドが前のメソッドが最初に終了するのを待つでしょうか? (私は自分のアプリケーション全体で使用するクラスのインスタンスを1つしか持っていないことに注意してください) – gaborous

+1

完全に空白でなければなりませんが、ソリューションに関係なく、スレッドに関係なく多くのスレッドで問題になります。これが心配な場合は、別々のプロセスに分割したり、複数のインスタンスを負荷分散の背後で実行したりしてください。 – sean

答えて

10

genTaskの例は実際には非同期呼び出しを実装する最良の方法です。この例ではPythonコルーチンのを使用していますが、私はの収量はジェネレータの値を返すために使用されたと思っていたので、一目で分かりません。

具体例:

  • 歩留まり、実際にはコルーチン(または擬似スレッドを生成します:ここで重要なことは二つの組み合わせは

    class MyHandler(tornado.web.RequestHandler): 
    
        @asynchronous 
        @gen.engine 
        def get(self): 
         response = yield gen.Task(self.dosomething, 'argument') 
    

    です非常に効率的であり、並行性が高くなるために行われます)。あなたはブロッキング機能上のコルーチンを起動すれば、それは非同期ではありませんので、非ブロック(非同期)関数です http://www.python.org/dev/peps/pep-0342/

  • gen.Task()gen.Task()は、特にPythonのコルーチン構文で動作するように、Tornadoによって提供されています。もっとに関する情報: http://www.tornadoweb.org/documentation/gen.html

コルーチンを使用してPythonで非同期呼び出しのだから、標準的な例:今

response = yield non_blocking_func(**kwargs) 
+1

ここにコルーチンと古いコールバックの実装の詳細が記載されている別の投稿もあります: http://stackoverflow.com/questions/8812715/using-a-simple-python-generator-as-a-co-routine-in -a-tornado-async-handler?rq = 1 – gaborous

1

Documentationは解決策を持っています。

簡単な例:

import os.path 
import tornado.web 
from tornado import gen 

class MyHandler(tornado.web.RequestHandler): 

    @gen.coroutine 
    def get(self, filename): 
     result = yield self.some_usefull_process(filename) 
     self.write(result) 

    @gen.coroutine 
    def some_usefull_process(self, filename): 
     if not os.path.exists(filename): 
      status = yield self.generate_file(filename) 
      result = 'File created' 
     else: 
      result = 'File exists' 

     raise gen.Return(result) 

    @gen.coroutine 
    def generate_file(self, filename): 
     fd = open(filename, 'w') 
     fd.write('created') 
     fd.close() 
関連する問題