简体   繁体   English

为什么我不能在协程调用的协程中发送websocket?

[英]Why can't I send down a websocket in a coroutine called by a coroutine?

Why does: 为什么:

async def setup():
    async with websockets.connect('ws:/ip.address:port') as ws:
        await ws.send('TEST MESSAGE')

def startup():
    loop = asyncio.new_event_loop() # because it's running in a thread
    asyncio.set_event_loop(loop)
    asyncio.ensure_future(setup())
    loop.run_forever()

send a message down the websocket and: 通过网络套接字发送消息,并:

async def setup():
    async with websockets.connect('ws:/ip.address:port') as ws:
        loop = asyncio.get_event_loop()
        loop.create_task(send_messages(ws))

async def send_messages(ws):
    await ws.send('TEST MESSAGE')

def startup():
    loop = asyncio.new_event_loop() # because it's running in a thread
    asyncio.set_event_loop(loop)
    asyncio.ensure_future(setup())
    loop.run_forever()

doesn't? 不?

I've cut down the code from my code to simplify it - can post the original if necessary. 我从代码中缩减了代码以简化代码-如有必要,可以发布原始代码。 The second version seems to hang at the await ws.send('test') part from turning on logging, debugging etc. 第二个版本似乎由于打开日志记录,调试等而挂在了等待ws.send('test')部分上。

I wondered if it was an issue with passing the websocket connection as an argument. 我想知道将websocket连接作为参数传递是否存在问题。 If you log what is passed and what is received there, they both return <websockets.client.WebSocketClientProtocol object at 0x04B51A90> with the same address both times. 如果您记录传递的内容和<websockets.client.WebSocketClientProtocol object at 0x04B51A90>接收的内容,它们都会两次返回具有相同地址的<websockets.client.WebSocketClientProtocol object at 0x04B51A90>

What I ultimately want to do, and suggestions for how to do this are welcome even if the question can't be answered is: 我最终想做的是,即使无法解决问题,也欢迎提出建议:

Have two coroutines running, pretty much forever that: * take messages from a queue put there by regular functions from the tkinter GUI and send them down the websocket * take messages from the websocket and alter things in the GUI 有两个协程正在运行,几乎永远是这样:*从tkinter GUI的常规函数​​中取出放置在队列中的消息,并将其发送到websocket上*从websocket接收消息并在GUI中进行更改

I thought the websockets library as asyncio would be the way to do this, but am open to any suggestions. 我认为将websockets库作为asyncio可以做到这一点,但是可以接受任何建议。

EDIT: forgot to add the error message! 编辑:忘记添加错误信息!

2017-03-19 10:49:31,103 ERROR asyncio Task exception was never retrieved
future: <Task finished coro=<send_messages() done, defined at chessboard.py:74> exception=ConnectionClosed('WebSocket connection is closed: code = 1000, no reason.',) created at chessboard.py:103>
source_traceback: Object created at (most recent call last):
  File "C:\Program Files (x86)\Python35-32\lib\threading.py", line 882, in _bootstrap
    self._bootstrap_inner()
  File "C:\Program Files (x86)\Python35-32\lib\threading.py", line 914, in _bootstrap_inner
    self.run()
  File "C:\Program Files (x86)\Python35-32\lib\threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "chessboard.py", line 120, in startup
    loop.run_forever()
  File "C:\Program Files (x86)\Python35-32\lib\asyncio\base_events.py", line 345, in run_forever
    self._run_once()
  File "C:\Program Files (x86)\Python35-32\lib\asyncio\base_events.py", line 1312, in _run_once
    handle._run()
  File "C:\Program Files (x86)\Python35-32\lib\asyncio\events.py", line 125, in _run
    self._callback(*self._args)
  File "C:\Program Files (x86)\Python35-32\lib\asyncio\tasks.py", line 307, in _wakeup
    self._step()
  File "C:\Program Files (x86)\Python35-32\lib\asyncio\tasks.py", line 239, in _step
    result = coro.send(None)
  File "chessboard.py", line 103, in setup
    loop.create_task(send_messages(ws))
Traceback (most recent call last):
  File "C:\Program Files (x86)\Python35-32\lib\asyncio\tasks.py", line 239, in _step
    result = coro.send(None)
  File "C:\Program Files (x86)\Python35-32\lib\asyncio\coroutines.py", line 121, in send
    return self.gen.send(value)
  File "chessboard.py", line 81, in send_messages
    await ws.send(str(message))#seems to be stopping here - why isn't it sending?
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\websockets\protocol.py", line 309, in send
    yield from self.ensure_open()
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\websockets\protocol.py", line 401, in ensure_open
    raise ConnectionClosed(self.close_code, self.close_reason)
websockets.exceptions.ConnectionClosed: WebSocket connection is closed: code = 1000, no reason.

It is fine to pass the websocket as an argument. 可以将websocket作为参数传递。 The problem here is that the websocket connection is already closed when the send coroutine is awaited (as explained in your error message). 这里的问题是,等待send协程时,websocket连接已经关闭(如错误消息中所述)。 That happens because the connection context finishes before the send_messages task can send the message. 发生这种情况是因为连接上下文在send_messages任务可以发送消息之前完成。

Instead, consider this working example: 相反,请考虑以下工作示例:

async def main():
    async with websockets.connect('ws:/ip.address:port') as ws:
        await send_messages(ws)

async def send_messages(ws):
    await ws.send('TEST MESSAGE')


loop = asyncio.get_event_loop()
loop.run_until_complete(main)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM