免責事項: これはおそらく非常に基本的な質問ですが、概念を理解していないため、目的を達成できません。
asyncio を使用して基本的なエコー クライアント サーバーを実装しようとしています。ドキュメントに含まれているサンプルから始めました。
私が達成したいのは、クライアントが即時接続以外のときにいつでもサーバーにデータを送信してから応答を読み取ることができる永続的な接続です(存在する場合)。接続は、明示的に閉じるまで両端で開いたままにする必要があります。
私はプロトコルのサンプルでこれをやっています。他の質問/ドキュメントを読むと、を使用してこれを実装できるようですがloop.call_later()
、これは本当に良い解決策ですか? Queue
理想的には、新しいパケットに即座に応答できるようにするためにa を使用したいと思います。
「MyProtocol. 初期化`:
@asyncio.coroutine
def writer():
global out_queue
while True:
packt = yield from out_queue.get()
print("yeahhh packet yummy")
data = bytes(packt.to_json(), 'ascii')
self.transport.write(data)
asyncio.async(writer())
しかし、これは何もしません。メインクライアントコードから新しいアイテムが挿入されると、すぐにメッセージが出力されると思います。何も起こりません...
さらにデバッグすると、キューがいっぱいになっていることが示されますが、out_queue.get() コルーチンは返されません。最初に、out_queue.put はアイテムを最初の .get() 呼び出しのウェイターにほとんど直接入れますが、まるでループが実行されていないかのようです。これは、クライアント接続全体に使用されるのと同じループです (すべてをスレッドに配置したため、新しいループを作成しました)。私が確認したところ、 .put() 呼び出しから行われた適切な呼び出しはすべてこのループ用です。
念のために言っておきますが、私は pip で asyncio install を使って Python 3.3 でこれを実行しています。
更新:これは、アイテムをキューに挿入しようとする方法です:
def send_packet(loop, queue, packet):
# this runs in main thread, not the loop thread
def f():
print("putting packet into queue")
queue.put_nowait(packet) # MUST NOT use .put() as it's a coroutine
loop.call_soon_threadsafe(f)
# !!! next one doesn't work !!!
# loop.call_soon_threadsafe(any_normal_function_with_coroutine_calls())
はprint
決して実行されません。