The following code connects invokes two websockets and repeatedly calculates and outputs a live quotient using one value from each feed. I'm trying to figure out how to properly handle exiting the loops. Right now I must hit Ctrl+C twice to exit the code. The output freezes on the first Ctrl+C, then returns a slew of exceptions on the second Ctrl+C. See below for code and exceptions output.
import asyncio
import websockets
import json
async def main():
queue = asyncio.Queue(10)
await asyncio.gather(func1(queue), func2(queue), func3(queue))
async def func1(queue):
async with websockets.connect("mystream1") as websocket1:
async for message in websocket1:
json_msg = json.loads(message)
await queue.put((json_msg["s"], json_msg["b"]))
async def func2(queue):
async with websockets.connect("mystream2") as websocket1:
async for message in websocket1:
json_msg = json.loads(message)
await queue.put((json_msg["s"], json_msg["a"]))
async def func3(queue):
symbol1 = ""
symbol2 = ""
price1 = 0
price2 = 0
while True:
key, value = await queue.get()
if key == "X":
price2 = float(value)
symbol2 = key
else:
price1 = float(value)
symbol1 = key
if symbol1 == "Y" and symbol2 == "X":
print(price2 / price1)
asyncio.run(main())
Here is the output once I hit Ctrl+C twice. Kindly advise how I can amend/augment the code to minimize/handle the exceptions. Thank you.
Traceback (most recent call last): File "C:\Python38\lib\asyncio\runners.py", line 44, in run return loop.run_until_complete(main) File "C:\Python38\lib\asyncio\base_events.py", line 603, in run_until_complete self.run_forever() File "C:\Python38\lib\asyncio\windows_events.py", line 316, in run_forever super().run_forever() File "C:\Python38\lib\asyncio\base_events.py", line 570, in run_forever self._run_once() File "C:\Python38\lib\asyncio\base_events.py", line 1823, in _run_once event_list = self._selector.select(timeout) File "C:\Python38\lib\asyncio\windows_events.py", line 434, in select self._poll(timeout) File "C:\Python38\lib\asyncio\windows_events.py", line 783, in _poll status = _overlapped.GetQueuedCompletionStatus(self._iocp, ms) KeyboardInterrupt
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "testws4.py", line 54, in asyncio.run(main()) File "C:\Python38\lib\asyncio\runners.py", line 47, in run _cancel_all_tasks(loop) File "C:\Python38\lib\asyncio\runners.py", line 62, in _cancel_all_tasks loop.run_until_complete( File "C:\Python38\lib\asyncio\base_events.py", line 603, in run_until_complete self.run_forever() File "C:\Python38\lib\asyncio\windows_events.py", line 316, in run_forever super().run_forever() File "C:\Python38\lib\asyncio\base_events.py", line 570, in run_forever self._run_once() File "C:\Python38\lib\asyncio\base_events.py", line 1823, in _run_once event_list = self._selector.select(timeout) File "C:\Python38\lib\asyncio\windows_events.py", line 434, in select self._poll(timeout) File "C:\Python38\lib\asyncio\windows_events.py", line 783, in _poll status = _overlapped.GetQueuedCompletionStatus(self._iocp, ms) KeyboardInterrupt Task was destroyed but it is pending! task: <Task pending name='Task-7' coro=<WebSocketCommonProtocol.close_connection() running at C:\Python38\lib\site-packages\websockets\protocol.py:1179> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x000001A07EE7C940>()]> cb=[gather.._done_callback() at C:\Python38\lib\asyncio\tasks.py:769, shield.._inner_done_callback() at C:\Python38\lib\asyncio\tasks.py:885]> Fatal error on SSL transport protocol: <asyncio.sslproto.SSLProtocol object at 0x000001A07EE31F40> transport: <_ProactorSocketTransport fd=472 read=<_OverlappedFuture cancelled>> Traceback (most recent call last): File "C:\Python38\lib\site-packages\websockets\protocol.py", line 1179, in close_connection if await self.wait_for_connection_lost(): GeneratorExit
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "C:\Python38\lib\asyncio\sslproto.py", line 685, in _process_write_backlog self._transport.write(chunk) File "C:\Python38\lib\asyncio\proactor_events.py", line 359, in write self._loop_writing(data=bytes(data)) File "C:\Python38\lib\asyncio\proactor_events.py", line 395, in _loop_writing self._write_fut = self._loop._proactor.send(self._sock, data) AttributeError: 'NoneType' object has no attribute 'send' Exception ignored in: <coroutine object WebSocketCommonProtocol.close_connection at 0x000001A07EE329C0> Traceback (most recent call last): File "C:\Python38\lib\site-packages\websockets\protocol.py", line 1204, in close_connection File "C:\Python38\lib\asyncio\sslproto.py", line 317, in close File "C:\Python38\lib\asyncio\sslproto.py", line 594, in _start_shutdown File "C:\Python38\lib\asyncio\sslproto.py", line 599, in _write_appdata File "C:\Python38\lib\asyncio\sslproto.py", line 707, in _process_write_backlog File "C:\Python38\lib\asyncio\sslproto.py", line 721, in _fatal_error
File "C:\Python38\lib\asyncio\proactor_events.py", line 151, in _force_close File "C:\Python38\lib\asyncio\base_events.py", line 719, in call_soon File "C:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed RuntimeError: Event loop is closed ^C