2016-05-24 1 views
10

asyncioを使用して非同期のクライアント/サーバーをセットアップしようとしています。Python asyncio:yield fromは将来使用されませんでしたか?

何らかの理由で、クライアントを実行しているときに私はAssertionError: yield from wasn't used with futureを取得しています。

このエラーを検索しても、それほど大きくはなりませんでした。
このエラーは何を意味し、何が原因ですか?

#!/usr/bin/env python3 

import asyncio 
import pickle 
import uuid 

port = 9999 

class ClientProtocol(asyncio.Protocol): 
    def __init__(self, loop): 
     self.loop = loop 
     self.conn = None 
     self.uuid = uuid.uuid4() 
     self.other_clients = [] 

    def connection_made(self, transport): 
     print("Connected to server") 
     self.conn = transport 

     m = "hello" 
     self.conn.write(m) 

    def data_received(self, data): 
     print('Data received: {!r}'.format(data)) 


    def connection_lost(self, exc): 
     print('The server closed the connection') 
     print('Stop the event loop') 
     self.loop.stop() 



# note that in my use-case, main() is called continuously by an external game engine 
client_init = False 
def main(): 
    # use a global here only for the purpose of providing example code runnable outside of aforementioned game engine 
    global client_init 

    if client_init != True: 
     loop = asyncio.get_event_loop() 
     coro = loop.create_connection(lambda: ClientProtocol(loop), '127.0.0.1', port) 
     task = asyncio.Task(coro) 

     transport, protocol = loop.run_until_complete(coro) 

     client_init = True 

    # to avoid blocking the execution of main (and of game engine calling it), only run one iteration of the event loop 
    loop.stop() 
    loop.run_forever() 

    if transport: 
     transport.write("some data") 

if __name__ == "__main__": 
    main() 

トレースバック:

Traceback (most recent call last): 
    File "TCPclient.py", line 57, in <module> 
    main() 
    File "TCPclient.py", line 45, in main 
    transport, protocol = loop.run_until_complete(coro) 
    File "/usr/lib/python3.5/asyncio/base_events.py", line 337, in run_until_complete 
    return future.result() 
    File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result 
    raise self._exception 
    File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step 
    result = coro.send(None) 
    File "/usr/lib/python3.5/asyncio/base_events.py", line 599, in create_connection 
    yield from tasks.wait(fs, loop=self) 
    File "/usr/lib/python3.5/asyncio/tasks.py", line 341, in wait 
    return (yield from _wait(fs, timeout, return_when, loop)) 
    File "/usr/lib/python3.5/asyncio/tasks.py", line 424, in _wait 
    yield from waiter 
    File "/usr/lib/python3.5/asyncio/futures.py", line 359, in __iter__ 
    assert self.done(), "yield from wasn't used with future" 
AssertionError: yield from wasn't used with future 
+1

'main()'で 'coro'から' task'を作成しますが、それを使用しません - それは 'loop.run_until_complete'に渡されるはずですか? –

答えて

8

問題は、あなたのコルーチンからタスクを作成したが、その後その代わりrun_until_completeにコルーチンを渡すことのようです:どちらか一方

coro = loop.create_connection(lambda: ClientProtocol(loop), '127.0.0.1', port) 
    task = asyncio.Task(coro) 

    transport, protocol = loop.run_until_complete(coro) 

タスクを渡します:

coro = loop.create_connection(lambda: ClientProtocol(loop), '127.0.0.1', port) 
    task = asyncio.Task(coro) 

    transport, protocol = loop.run_until_complete(task) 

タスクを作成せずにコルーチンを渡してください。 run_until_completeはまたあなた

coro = loop.create_connection(lambda: ClientProtocol(loop), '127.0.0.1', port) 

    transport, protocol = loop.run_until_complete(coro) 

のためのタスクを作成します、あなたは、バイト文字列で記述している文字列を確認する必要があります。 Python 3の文字列リテラルは、デフォルトでUnicodeになります。これはしかし、run_until_completeのソースは、これは言っている、問題である理由あなたはそれが私にははっきりしていない最初の場所で

EDITをバイト文字列をこれらをコード化するか、単に書くことができ、次のいずれか

警告:run_until_complete() を同じコルーチンで2回呼び出すのは悲惨です。つまり、別の2つのタスクに2つのラップを入れても問題ありません。

タスクを作成してコルーチン(タスクを作成する)を渡すと同じ効果があるとします。

関連する問題