Я хочу сделать программу сервер / клиент на основе веб-сокетов (сервер + клиент) и пользовательского интерфейса urwid на стороне клиента.
Проблема, с которой я сталкиваюсь, заключается в том, что я продолжаю получать "Исключение задачи никогда не было"Я работаю, но это не чисто ....
Мой сервер:
import asyncio, websockets, random, json
connected = set()
##########################
# end-less loop routines
##########################
async def handle_read_external_data():
# now sumulated by an asyncio sleep of 1 second and random generator
await asyncio.sleep(1)
data = {'value': (random.random() * 0.4) - 0.2 + 40}
return data
async def broadcast_task():
global connected
while True:
data = await handle_read_external_data()
data_json = json.dumps(data)
print ("len:", len(connected))
if connected != set():
try:
await asyncio.wait([ws.send(data_json) for ws in connected])
except Exception as e:
print (e)
##########################
# websockets
##########################
async def consumer_handler(websocket, path):
global connected
# Register.
connected.add(websocket)
try:
async for message in websocket:
print (message)
except Exception as e:
print ("Unregister websocket")
connected.remove(websocket)
##########################
# Asyncio event loop
##########################
def start_event_loop():
loop = asyncio.get_event_loop()
tasks = asyncio.gather(
broadcast_task(),
websockets.serve(consumer_handler, '0.0.0.0', 8765),
)
try:
loop.run_until_complete(tasks)
except Exception:
print("exception consumed")
except BaseException:
print("caught BaseException!")
raise
finally:
loop.close()
if __name__ == "__main__":
start_event_loop()
Мой клиент:
import asyncio, websockets, json, urwid
loop = asyncio.get_event_loop()
evl = urwid.AsyncioEventLoop(loop=loop)
urwid_loop = None
tasks = None
txt = urwid.Text(u"Hello World")
fill = urwid.Filler(txt, 'top')
def show_or_exit(key):
if key in ('q', 'Q'):
global tasks
tasks.cancel()
raise urwid.ExitMainLoop()
return key
async def consumer_handler():
async with websockets.connect('ws://localhost:8765') as websocket:
async for message in websocket:
data = json.loads(message)
txt.set_text ("data: {}".format (data['value']))
def main ():
global urwid_loop, tasks, loop, evl
urwid_loop = urwid.MainLoop(fill, event_loop=evl, unhandled_input=show_or_exit)
urwid_loop.start()
tasks = asyncio.gather(consumer_handler())
try:
loop.run_until_complete(tasks)
except asyncio.CancelledError:
pass
urwid_loop.stop()
loop.close()
if __name__ == "__main__":
main()
Когда я запускаюсервер, который я получил:
len: 0
len: 0
len: 0
...
Пока все хорошо.Когда я запускаю клиент, сервер показывает мне:
len: 0
len: 0
len: 1
len: 1
len: 1
...
В тот момент, когда я нажимаю CTRL + C на клиенте, я получил:
len: 1
Unregister websocket
len: 0
Это требуемое поведение, кромечто в клиенте я получил исключение, и мой терминал «поврежден», поскольку он все еще находится в режиме «urwid».
Чистый выход, нажав кнопку Q, он дает чистый выход для клиента,и терминал в порядке.На стороне сервера появляется сообщение " Исключение задачи не было получено ", а переменная "connected" по-прежнему содержит закрытый веб-сокет.
Task exception was never retrieved
future: <Task finished coro=<WebSocketCommonProtocol.send() done, defined at ><path-to-python-install>/lib/python3.6/site-packages/websockets/protocol.py:325> exception=ConnectionClosed('WebSocket connection is closed: code = 1000 (OK), no reason',)>
Traceback (most recent call last):
File "<path-to-python-install>/lib/python3.6/site-packages/websockets/protocol.py", line 334, in send
yield from self.ensure_open()
File "<path-to-python-install>/lib/python3.6/site-packages/websockets/protocol.py", line 470, in ensure_open
raise ConnectionClosed(self.close_code, self.close_reason)
websockets.exceptions.ConnectionClosed: WebSocket connection is closed: code = 1000 (OK), no reason
len: 1
Task exception was never retrieved
...
Кто-нибудь знает?