ホームページ  >  記事  >  バックエンド開発  >  Tornadoのコルーチンを使ったプログラミング

Tornadoのコルーチンを使ったプログラミング

高洛峰
高洛峰オリジナル
2016-10-17 14:13:531152ブラウズ

tornado3 のリリース後、非同期プログラミングではコルーチンの概念が強化され、元の gen.engine に取って代わり、現在の gen.coroutine になりました。このデコレーターはもともと、トルネードでの非同期プログラミングを簡素化するために設計されました。コールバック関数の記述を避け、通常の論理的思考と一貫した開発を可能にします。簡単な例は次のとおりです。


class MaindHandler(web.RequestHandler):

@asynchronous

@gen.coroutine

def post(self):

client = AsyncHTTPClient()

resp = yield client .fetch(https://api.github.com/users")

if resp.code == 200:

resp =scape.json_decode(resp.body)

self.write(json.dumps(resp) , indent=4, separators=(',', ':')))

else:

resp = {"message": "何かを取得するときにエラーが発生しました"}

' s 'の ‐ ‐ - - self.write(json.dumps(resp、indent)= 4、separators = {'、'、 '、'))

self.finish() resp が戻った後も実行を継続します。REST スタイルの API を構築する場合、データを整形した後にブラウザからアクセスすることが多いため、ここでは tornado に付属するescape.json_encode の代わりに json.dumps が使用されます。実際、escape.json_encode は、より多くの機能をパッケージ化するためにプル リクエストを送信したときの答えです。すべての json 関数を提供するつもりはありません。ユーザーは json モジュールを直接使用できます


以前のブログで、Tornado の非同期機能の使用について説明しました。そうしないと、単一のプロセスがブロックされ、非同期効果がまったく得られなくなります。Tornado で最も一般的に使用される非同期ライブラリは、そのライブラリに基づいて実装された OpenID ログイン検証インターフェイスです。ここで見つかります。一般的に使用される MongoDB ドライバーが含まれます。


バージョン 3.0 以降、gen.coroutine モジュールがより目立つようになります。コルーチン デコレータを使用すると、コールバックに依存する非同期プログラミングを同期プログラミングのように見せることができます。その中には、Python のジェネレーターの Send 関数があります。ジェネレーターでは、yield キーワードは通常の関数の return と比較されることがよくあります。これはイテレータとして使用できるため、next() を使用して yield の結果を返すことができます。ただし、ジェネレーターを使用する別の方法として、send メソッドを使用する方法があります。ジェネレーター内では、yield 結果を変数に割り当てることができ、この値は外部ジェネレーター クライアントを通じて送信されます。例を挙げます:


def test_yield():

pirnt "test yield"

Say = (yield)

print Says

if __name__ == "__main__":

client =収量()

client.next()

client.send("hello world")

出力結果は以下の通りです:

test yeild

hello world

すでに実行されている関数はハングします。呼び出されるまで、クライアントは send メソッドを使用し、元の関数は実行を続けます。ここでの gen.coroutine メソッドは、必要な操作を非同期で実行し、結果が返されるのを待ってから元の関数に送信します。このようにして、同期的に記述されたコードは実行を継続します。非同期実行の影響。

Tornado 非同期プログラミング


コルーチンを使用して、関数を分離した非同期プログラミングを実装します。詳細は次のとおりです:


@gen.coroutine

def post(self):

client = AsyncHTTPClient()

resp = yield client.fetch("https://api.github.com/ユーザー")

if resp == 200:

body =escape.json_decode(resy.body)

else:

body = {"メッセージ": "クライアント取得エラー"}

logger.error("client fetch error% d, %s" % (resp.code, resp.message))

self.write(escape.json_encode(body))

self.finish()

関数に変更すると、次のようになります。このように;

@gen.coroutime

def post(self):

resp = yield GetUser()

self.write(resp)

@gen.coroutine

def GetUser( ):

client = AsyncHTTPClient()

resp = yield client.fetch("https://api.github.com/users")

if resp.code == 200:

resp =scape.json_decode( resp.body)

else:

using using 's out out's out' out' out' out way out'一緒に出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出て出出して‐ に (それぞれ)

ここで、非同期が関数内にカプセル化されている場合、通常のプログラムのように return キーワードを使用して戻るのではなく、gen モジュールは gen.Return メソッドを提供します。これは raise メソッドによって実現されます。これはジェネレーターを使用して実装されているという事実にも関係しています。


コルーチンを使用してスケジュールされたタスクを実行します


Tornadoにはそのようなメソッドがあります:


tornado.ioloop.IOLoop.instance().add_timeout()

このメソッドは非time.sleep の拡張機能。時間の長さと関数の 2 つのパラメータを受け入れるブロッキング バージョン。関数が呼び出されるまでの時間を示します。ここでは ioloop に基づいているため、ノンブロッキングです。このメソッドは、クライアントの長時間接続やコールバック関数のプログラミングでよく使用されます。ただし、これを使用してスケジュールされたタスクを実行することは役に立ちません。通常、スケジュールされたタスクを実行する場合にはこれを使用する必要はありません。しかし、heroku を使っていると、クレジット カードを登録しないと、単純な Web アプリケーションのホスティングしか利用できないことがわかりました。実行するスケジュールされたタスクを追加できません。そこでこんな方法を思いつきました。ここでは、主に Github API インターフェースを介して一定間隔でデータを取得するために使用します。使用方法は以下の通りです:


デコレーター


def sync_loop_call(delta=60 *​​ 1000):

"""

func downを待ってからadd_timeoutを処理

"""

def wrap_loop(func):r r start at%d "%

_(func .__ name __、int(time.time()))try:

evelow func(*args、** kwargs)

exception例外を除いて、e:

options.logger.error( "function%r error:%s"%

(func .__ name__、int(time.time()):)

タスク関数

@sync_loop_call (delta=10 * 1000)

def worker():

"""

何かをする

"""

タスクを追加

if __name__ = = "__main__":

worker()

app.listen(options.port)

tornado.ioloop.IOLoop.instance().start()

これを実行した後、Web アプリケーションが起動すると、スケジュールされたタスクがこれはイベントベースで非同期に実行されるため、Web サービスの通常の動作には影響しません。もちろん、タスクがブロックされたり、計算量が多くなったりすることはありません。ここでは主にデータをキャプチャしており、Tornado に付属している非同期キャプチャ方法を使用しています。


sync_loop_call デコレータで、wrap_func 関数に @gen.coroutine デコレータを追加しました。これにより、yeild 関数が実行された後にのみ add_timeout 操作が実行されるようになります。 @gen.coroutine デコレーターなし。その後、yield が返されるのを待たずに add_timeout が実行されます。

完全な例については、私の Github を参照してください。このプロジェクトは Heroku 上に構築されています。 Github ユーザーアクティビティランキングとユーザーの地域分布を表示するために使用されます。 Github-Data にアクセスして表示できます。中国では Heroku がブロックされているため、アクセスするには壁を乗り越える必要があります。

概要


Tornado はノンブロッキング Web サーバーおよび Web フレームワークですが、使用する場合、非同期ライブラリのみがその非同期の利点を実際に活用できるわけではありません。非常に高く、詰まりが特に深刻でない場合は問題ありません。また、非同期プログラミングでコルーチンモジュールを使用する場合、関数内にカプセル化すると、関数の実行中にエラーが発生してもキャッチしなければスローされないため、デバッグが非常に困難になります。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。