2016-10-04 13 views
2

私はPython asyncioを勉強するためのスニペットを書こうとしています。基本的な考え方は次のとおりです。asyncioを使用すると、一部のデータをタイムリーに更新し、aiohttp経由で表示できますか?

  1. は、ユーザーへのデータの復帰がここに速やか

を変更します

  • ユーザーにいくつかのデータを提示する「単純な」ウェブサーバ(aiohttp)を使用していますコード:

    import asyncio 
    import random 
    from aiohttp import web 
    
    userfeed = [] # the data suppose to return to the user via web browsers 
    
    async def data_updater(): #to simulate data change promptly 
        while True: 
         await asyncio.sleep(3) 
         userfeed = [x for x in range(random.randint(1, 20))] 
         print('user date updated: ', userfeed) 
    
    
    async def web_handle(request): 
        text = str(userfeed) 
        #print('in handler:', text) # why text is empty? 
        return web.Response(text=text) 
    
    async def init(loop): 
        app = web.Application(loop=loop) 
        app.router.add_route('GET', '/', web_handle) 
        srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8000) 
        print('Server started @ http://127.0.0.1:8000...') 
        return srv 
    
    loop = asyncio.get_event_loop() 
    asyncio.ensure_future(data_updater()) 
    asyncio.ensure_future(init(loop)) 
    loop.run_forever() 
    

    問題は、コードが実行されている(のpython 3.5)が、が更新されていない理由は

    1. :-(web_handler()でもブラウザで常に空であると?
    2. この機能に関して、更新メカニズムが複雑になる可能性があるため、後でasync IO waitが含まれる可能性があります。をdata_updater()に使用する代わりに、より正確なタイマーを取得する方が良いでしょうか?
  • +0

    あなたのページを閲覧しているユーザーに通知を送信したいですか(そのユーザーの操作なし)?もしそうなら、あなたは* websocket *技術を見てください。これはかなり簡単な方法で 'aiohttp'に実装されています([examples](https://github.com/KeepSafe/aiohttp/blob/master/)です) examples/web_ws.py)をソースコードに追加します)。それ以外の場合は、関数間で 'userfeed'変数を渡すための' 'app'オブジェクト(http://aiohttp.readthedocs.io/en/stable/faq.html#id3)(' dict'インタフェースを提供する)を使用してくださいそれをグローバルにすることは避けてください。 – mgc

    +0

    @ mgc、返信ありがとうございます。私はデータが自動的にユーザーのブラウザでフラッシュされるのを望んでいません。ちょうどクライアントのプルモデルで十分です.Wgetのようなブラウザやツールを使ってURLを開くたびに最新のデータが表示されます。ここで混乱するのは、なぜグローバル変数が更新されていないのですか?(web_handler()内のprintは常に[]ですが、 'data _updater()'は変更されたものを表示します)?非同期defは通常のdefとは異なりますが、何らかの形でコンテキストをキャッシュしますか? – user340307

    +0

    この文脈でのグローバル変数の使用は、[documentation](http://aiohttp.readthedocs.io/en/stable/web.html#data-sharing-aka-no-html)で明示的に推奨されていないので、シングルトン - してください)。しかし、本当にグローバルな 'userfeed'を使って動作させる必要があれば、' data_updated'と 'web_handle'の両方の関数に' global userfeed'を追加すれば動作します(このように 'userfeed'は変数を参照しますあなたの例では、各関数はローカルな 'userfeed'を持っていました)。 – mgc

    答えて

    1

    主な問題は、あなたが両方data_updaterweb_handle機能で声明global userfeedを忘れていることです。したがって、how python resolves scopesによれば、web_handleで定義したグローバル変数を参照していました。data_updaterには、userfeed = [x for x ...というステートメントで作成されたローカル変数があります。このコンテキストでのグローバル変数の使用は、明示的にはdiscouragedであるため、aiohttp.web.Applicationオブジェクトのdictインターフェイスを使用して関数間の変数を安全に参照する例があります。

    import asyncio 
    import random 
    from aiohttp import web 
    
    
    async def data_updater(app): 
        while True: 
         await asyncio.sleep(3) 
         app["userfeed"] = [x for x in range(random.randint(1, 20))] 
    
    async def web_handle(request): 
        userfeed = request.app["userfeed"] 
        return web.Response(text=str(userfeed)) 
    
    async def init(loop, port=8000): 
        app = web.Application(loop=loop) 
        app.router.add_route('GET', '/', web_handle) 
        handler = app.make_handler() 
        srv = await loop.create_server(
         handler, '127.0.0.1', port=port) 
        return srv, app, handler 
    
    if __name__ == "__main__": 
        loop = asyncio.get_event_loop() 
        srv, app, handler = loop.run_until_complete(init(loop, 8000)) 
        app['userfeed'] = [] 
        asyncio.ensure_future(data_updater(app)) 
        try: 
         loop.run_forever() 
        except KeyboardInterrupt: 
         pass 
        finally: 
         srv.close() 
         loop.run_until_complete(srv.wait_closed()) 
         loop.run_until_complete(app.shutdown()) 
         loop.run_until_complete(handler.finish_connections(60.0)) 
         loop.run_until_complete(app.cleanup()) 
        loop.close() 
    

    あなたは127.0.0.1:8000ページを更新すると、彼らは(あなたがそれを確認するためにdata_updaterprint文を元に戻すことができます)3秒ごとにサーバ側を更新しているとあなたには、いくつかの新しい乱数を持っている必要があります。

    +0

    私は愚かなabcの間違いを作ったようです:(あなたの詳細な説明のための多くのおかげです、本当に感謝します – user340307

    +0

    助けてくれてうれしい! – mgc

    関連する問題