[英]Python websockets error handling: growing number of threads
我有一個非常簡單的 MWE - 兩個 WS 連接,其中一個會拋出錯誤。 兩者都作為任務執行,並且應該各自恢復。 不幸的是,我的實現導致線程數量增加(每個錯誤一個)。 我在這里做錯了什么?
import websockets
import asyncio
import json
uri = "wss://echo.websocket.org"
async def ws(error):
while True:
try:
async with websockets.connect(uri=uri) as websocket:
await websocket.send("foo")
async for message in websocket:
if error:
raise ValueError
print(message)
except:
print('caught a WS exception - going to sleep for 30 seconds')
websocket.close()
await asyncio.sleep(30)
async def main():
# try:
ws_task_error = loop.create_task(ws(error=True))
ws_task_fine = loop.create_task(ws(False))
await asyncio.wait([ws_task_error, ws_task_fine], return_when=asyncio.FIRST_EXCEPTION)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
據我了解,一旦我離開 websockets.connect() 的上下文管理器,負責的線程就應該被刪除。 我顯然沒有在這里正確實施它。 想法?
- - - 編輯 - - -
我感覺上面那個是WE,但不是真的M。這個例子在連接后立即強制異常。 在日志中,連接正確關閉。 盡管如此,我最終還是在每次連接時都創建了一個新線程。
import websockets
import asyncio
import logging
uri = "wss://echo.websocket.org"
logging.basicConfig(format='%(asctime)s %(levelname)s %(name)s: %(message)s')
logger = logging.getLogger('websockets')
logger.setLevel(logging.DEBUG)
async def ws():
while True:
async with websockets.connect(uri=uri) as websocket:
try:
raise ValueError
except:
print('Exception thrown')
print('Exiting...')
async def main():
ws_task_error = loop.create_task(ws())
await asyncio.wait([ws_task_error], return_when=asyncio.FIRST_EXCEPTION)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
輸出:
2020-01-21 10:44:04,710 DEBUG websockets.protocol: client - state = CONNECTING
2020-01-21 10:44:04,908 DEBUG websockets.protocol: client - event = connection_made(<asyncio.sslproto._SSLProtocolTransport object at 0x00000210389E6828>)
2020-01-21 10:44:05,001 DEBUG websockets.protocol: client - state = OPEN
Exception thrown
Exiting...
2020-01-21 10:44:05,003 DEBUG websockets.protocol: client - state = CLOSING
2020-01-21 10:44:05,003 DEBUG websockets.protocol: client > Frame(fin=True, opcode=8, data=b'\x03\xe8', rsv1=False, rsv2=False, rsv3=False)
2020-01-21 10:44:05,098 DEBUG websockets.protocol: client < Frame(fin=True, opcode=8, data=b'\x03\xe8', rsv1=False, rsv2=False, rsv3=False)
2020-01-21 10:44:05,099 DEBUG websockets.protocol: client - event = connection_lost(None)
2020-01-21 10:44:05,100 DEBUG websockets.protocol: client - state = CLOSED
2020-01-21 10:44:05,100 DEBUG websockets.protocol: client x code = 1000, reason = [no reason]
2020-01-21 10:44:05,100 DEBUG websockets.protocol: client x closing TCP connection
2020-01-21 10:44:05,193 DEBUG websockets.protocol: client - state = CONNECTING
2020-01-21 10:44:05,393 DEBUG websockets.protocol: client - event = connection_made(<asyncio.sslproto._SSLProtocolTransport object at 0x0000021038AB2908>)
2020-01-21 10:44:05,482 DEBUG websockets.protocol: client - state = OPEN
Exception thrown
Exiting...
2020-01-21 10:44:05,489 DEBUG websockets.protocol: client - state = CLOSING
2020-01-21 10:44:05,489 DEBUG websockets.protocol: client > Frame(fin=True, opcode=8, data=b'\x03\xe8', rsv1=False, rsv2=False, rsv3=False)
2020-01-21 10:44:05,580 DEBUG websockets.protocol: client < Frame(fin=True, opcode=8, data=b'\x03\xe8', rsv1=False, rsv2=False, rsv3=False)
2020-01-21 10:44:05,581 DEBUG websockets.protocol: client - event = connection_lost(None)
2020-01-21 10:44:05,582 DEBUG websockets.protocol: client - state = CLOSED
2020-01-21 10:44:05,582 DEBUG websockets.protocol: client x code = 1000, reason = [no reason]
2020-01-21 10:44:05,583 DEBUG websockets.protocol: client x closing TCP connection
2020-01-21 10:44:05,670 DEBUG websockets.protocol: client - state = CONNECTING
2020-01-21 10:44:05,863 DEBUG websockets.protocol: client - event = connection_made(<asyncio.sslproto._SSLProtocolTransport object at 0x0000021038AB2B70>)
2020-01-21 10:44:05,950 DEBUG websockets.protocol: client - state = OPEN
Exception thrown
Exiting...
2020-01-21 10:44:05,953 DEBUG websockets.protocol: client - state = CLOSING
2020-01-21 10:44:05,953 DEBUG websockets.protocol: client > Frame(fin=True, opcode=8, data=b'\x03\xe8', rsv1=False, rsv2=False, rsv3=False)
2020-01-21 10:44:06,036 DEBUG websockets.protocol: client < Frame(fin=True, opcode=8, data=b'\x03\xe8', rsv1=False, rsv2=False, rsv3=False)
2020-01-21 10:44:06,037 DEBUG websockets.protocol: client - event = connection_lost(None)
2020-01-21 10:44:06,037 DEBUG websockets.protocol: client - state = CLOSED
2020-01-21 10:44:06,038 DEBUG websockets.protocol: client x code = 1000, reason = [no reason]
2020-01-21 10:44:06,039 DEBUG websockets.protocol: client x closing TCP connection
2020-01-21 10:44:06,124 DEBUG websockets.protocol: client - state = CONNECTING
2020-01-21 10:44:06,308 DEBUG websockets.protocol: client - event = connection_made(<asyncio.sslproto._SSLProtocolTransport object at 0x0000021038AC6C50>)
2020-01-21 10:44:06,400 DEBUG websockets.protocol: client - state = OPEN
Exception thrown
Exiting...
2020-01-21 10:44:06,402 DEBUG websockets.protocol: client - state = CLOSING
2020-01-21 10:44:06,402 DEBUG websockets.protocol: client > Frame(fin=True, opcode=8, data=b'\x03\xe8', rsv1=False, rsv2=False, rsv3=False)
2020-01-21 10:44:06,495 DEBUG websockets.protocol: client < Frame(fin=True, opcode=8, data=b'\x03\xe8', rsv1=False, rsv2=False, rsv3=False)
2020-01-21 10:44:06,496 DEBUG websockets.protocol: client - event = connection_lost(None)
2020-01-21 10:44:06,496 DEBUG websockets.protocol: client - state = CLOSED
2020-01-21 10:44:06,496 DEBUG websockets.protocol: client x code = 1000, reason = [no reason]
2020-01-21 10:44:06,497 DEBUG websockets.protocol: client x closing TCP connection
2020-01-21 10:44:06,600 DEBUG websockets.protocol: client - state = CONNECTING
2020-01-21 10:44:06,827 DEBUG websockets.protocol: client - event = connection_made(<asyncio.sslproto._SSLProtocolTransport object at 0x0000021038AC6B70>)
2020-01-21 10:44:06,934 DEBUG websockets.protocol: client - state = OPEN
Exception thrown
Exiting...
2020-01-21 10:44:06,936 DEBUG websockets.protocol: client - state = CLOSING
2020-01-21 10:44:06,936 DEBUG websockets.protocol: client > Frame(fin=True, opcode=8, data=b'\x03\xe8', rsv1=False, rsv2=False, rsv3=False)
2020-01-21 10:44:07,042 DEBUG websockets.protocol: client < Frame(fin=True, opcode=8, data=b'\x03\xe8', rsv1=False, rsv2=False, rsv3=False)
2020-01-21 10:44:07,043 DEBUG websockets.protocol: client - event = connection_lost(None)
2020-01-21 10:44:07,044 DEBUG websockets.protocol: client - state = CLOSED
2020-01-21 10:44:07,044 DEBUG websockets.protocol: client x code = 1000, reason = [no reason]
2020-01-21 10:44:07,045 DEBUG websockets.protocol: client x closing TCP connection
while True:
應該async with websockets.connect(uri=uri) as websocket:
實際上,在您的示例中, ws_task_fine
任務async for message in websocket:
在第一條消息之后。 ws_task_error
任務循環,增加線程。
這是一個如何實現它的粗略示例:
import websockets
import asyncio
uri = "wss://echo.websocket.org"
async def ws(error):
async with websockets.connect(uri=uri) as websocket:
while True:
print('Starting...' + str(error))
try:
await websocket.send("foo")
message = await websocket.recv()
print(message)
if error:
raise ValueError('Exception')
except Exception as e:
print(e)
print('Finishing...' + str(error))
await asyncio.sleep(2)
async def main():
# try:
ws_task_error = loop.create_task(ws(error=True))
# ws_task_fine = loop.create_task(ws(False))
await asyncio.wait([ws_task_error])
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.run_forever()
loop.run_forever()
允許我們在每次完成時重新啟動main()
協程
輸出:
Starting...True
foo
Exception
Finishing...True
Starting...True
foo
Exception
Finishing...True
Starting...True
foo
Exception
Finishing...True
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.