Python asyncio websocket ConnectionClosed - python

i have multiple tasks that use websocket. i would like to detect the connection close of websocket and then reconnect the websocket, I'm doing it through a variable called break_task if it is true then in on of the task there was a connection close detection, below the code and the error exception I got (i use python 3.6):
break_task = False
async def value_1():
global break_task
msg_dict = deepcopy(MESG)
async with websockets.connect('wss://api.xxxxx') as ws:
await ws.send(json.dumps(msg_dict))
while break_task == False:
try:
res = await ws.recv()
except ConnectionClosed:
print('CONNECTION CLOSED raised exception in value_1() -> TRYING TO RECONNECT !!!')
break_task = True
break
async def value_2():
global break_task
auth_dict = deepcopy(PAYLOAD)
async with websockets.connect('wss://api.xxxxx') as ws:
await ws.send(json.dumps(auth_dict))
while break_task == False:
await asyncio.sleep(0.05)
try:
res = await ws.recv()
except ConnectionClosed:
print('CONNECTION CLOSED raised exception in value_2() -> TRYING TO RECONNECT !!!')
break_task = True
break
data = json.loads(res)
and...
while True:
if (break_task == False):
tasks = value_1(), value_2()
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*tasks))
elif (break_task == True):
tasks = None
loop.stop()
loop.close()
break_task = False
I get this result:
Traceback (most recent call last):
File "tija_v0.1.py", line 584, in <module>
loop.run_until_complete(asyncio.gather(*tasks))
File "C:\Dev\Anaconda2\envs\python36\lib\asyncio\tasks.py", line 589, in gather
fut = ensure_future(arg, loop=loop)
File "C:\Dev\Anaconda2\envs\python36\lib\asyncio\tasks.py", line 513, in ensure_future
task = loop.create_task(coro_or_future)
File "C:\Dev\Anaconda2\envs\python36\lib\asyncio\base_events.py", line 282, in create_task
self._check_closed()
File "C:\Dev\Anaconda2\envs\python36\lib\asyncio\base_events.py", line 357, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
sys:1: RuntimeWarning: coroutine 'value_2' was never awaited
sys:1: RuntimeWarning: coroutine 'value_1' was never awaited

sys:1: RuntimeWarning: coroutine 'value_2' was never awaited
sys:1: RuntimeWarning: coroutine 'value_1' was never awaited
might trip your process from reconnecting, it might effect in more severe way than a warning. I have similar problem when attempting to bind async message update_handler function to synchronic third party web socket message handler.
You should find a method to call the handler with await to prevent this warning.

Related

discord.py tasks.loop() sending runtime error : no running event loop

I am trying to make my bot send a message in a particular channel hourly using the discord.ext's tasks. Here's the buggy piece of code
#tasks.loop(hours = 1)
async def remindstudy():
await bot.wait_until_ready()
channel = bot.get_channel(1038719402658517054)
await channel.send("check")
remindstudy.start()
This is supposed to send the message "check" every hour but instead throws this error:
Traceback (most recent call last):
File "main.py", line 137, in <module>
remindstudy.start()
File "/home/runner/main-bore-ho-raha-hoon/venv/lib/python3.8/site-packages/discord/ext/tasks/__init__.py", line 398, in start
self._task = asyncio.create_task(self._loop(*args, **kwargs))
File "/nix/store/2vm88xw7513h9pyjyafw32cps51b0ia1-python3-3.8.12/lib/python3.8/asyncio/tasks.py", line 381, in create_task
loop = events.get_running_loop()
RuntimeError: no running event loop
sys:1: RuntimeWarning: coroutine 'Loop._loop' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
What is going wrong? I copied this code snippet from another old bot of mine, it is still running perfectly fine, but this bot won't run
The task.start method is expected to be called in an async function (coroutine), like in setup_hook, after the 2.0 update.
async def setup_hook():
remindstudy.start()
bot.setup_hook = setup_hook
#tasks.loop(hours = 1)
async def remindstudy():
await bot.wait_until_ready()
channel = bot.get_channel(1038719402658517054)
await channel.send("check")
See this example.

Running multiple bots in 1 script without warning

Goals
Running multiple bot in the same time with same command
What I've tried
I've coded and searching through internet I found this. I know it's the answer but if I created client1 and client2. Here in my code I just make 1 client (client1)
token1 = getenv("TOKEN1")
token2 = getenv("TOKEN2")
intents = discord.Intents().all()
client1 = commands.Bot(command_prefix = '.', intents = intents)
slash = SlashCommand(client1, sync_commands=True)
client1.remove_command('help')
#client1.event
async def on_ready():
await client1.change_presence(activity=discord.Game(name='Bot Ready'))
print("logged in")
for filename in listdir('cogs'):
if filename.endswith('.py'):
client1.load_extension(f'cogs.{filename[:-3]}')
def meFunction(ctx):
return ctx.author.id == 385053392059236353
loop = asyncio.get_event_loop()
loop.create_task(client1.start(token1))
loop.create_task(client1.start(token2))
loop.run_forever()
And then this warning message appear in my command prompt
client_session: <aiohttp.client.ClientSession object at 0x00000247DB381BE0>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x00000247DB370D60>, 2262.609)]']
connector: <aiohttp.connector.TCPConnector object at 0x00000247DB38E280>
Task exception was never retrieved
future: <Task finished name='Task-5' coro=<Client.start() done, defined at C:\Users\chris\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py:649> exception=RuntimeError('Concurrent call to receive() is not allowed')>
Traceback (most recent call last):
File "C:\Users\chris\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 666, in start
await self.connect(reconnect=reconnect)
File "C:\Users\chris\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 566, in connect
await self.ws.poll_event()
File "C:\Users\chris\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\gateway.py", line 555, in poll_event
msg = await self.socket.receive(timeout=self._max_heartbeat_timeout)
File "C:\Users\chris\AppData\Local\Programs\Python\Python39\lib\site-packages\aiohttp\client_ws.py", line 216, in receive
raise RuntimeError("Concurrent call to receive() is not allowed")
RuntimeError: Concurrent call to receive() is not allowed
Last solution what I know is making client2 which is copy of client1

Python RuntimeError: This event loop is already running

It is a very common issue, but I cannot actually find a proper answer to it. I have the following code to connect to a server through a websocket and I want to keep it alive and keep listening to messages it sends like below:
import asyncio
import websockets
import nest_asyncio
nest_asyncio.apply()
async def listen_for_message(websocket):
while True:
await asyncio.sleep(0)
message = await websocket.recv()
print(message)
async def connect_to_dealer():
websocket = await websockets.connect(websocketadress)
hello_message = await websocket.recv()
print(hello_message)
async def my_app():
websocket = await connect_to_dealer()
asyncio.ensure_future(listen_for_message(websocket))
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(my_app())
loop.run_forever()
And it raises the error:
File "\untitled0.py", line 71, in <module>
loop.run_forever()
File "\Anaconda3\lib\asyncio\base_events.py", line 525, in run_forever
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
And without the
import nest_asyncio
nest_asyncio.apply()
I get:
File "\untitled0.py", line 70, in <module>
loop.run_until_complete(my_app())
File "\Anaconda3\lib\asyncio\base_events.py", line 570, in run_until_complete
self.run_forever()
File "\Anaconda3\lib\asyncio\base_events.py", line 525, in run_forever
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
I still do not understand why it does this.
loop.run_until_complete() already runs your loop 'forever'.
Instead of firing of your listen_for_message() awaitable as a task, just await on it. That then runs forever, because listen_for_message() itself never returns:
async def my_app():
websocket = await connect_to_dealer()
await listen_for_message(websocket)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(my_app())
Note that your connect_to_dealer() function doesn't return the websocket; that's probably an oversight you want to correct:
async def connect_to_dealer():
return await websockets.connect(websocketadress)
I removed the hello_message = await websocket.recv() / print(hello_message) lines there because listen_for_message() will already receive messages and print them.

Why does calling asyncio.sleep causes websocket connection to close?

I am trying to build a websockets server where the client connects and sends a request of some kind, and then the server adds that request to a queue and returns something back when finished.
to simulate the process of queueing and waiting for tasks to finish, I called asyncio.sleep whenever the process is supposed to be called.
however, whenever I do that I get the following error from the client-side:
Traceback (most recent call last):
File "D:/Python/server/client1.py", line 10, in <module>
asyncio.get_event_loop().run_until_complete(message())
File "C:\ProgramData\Anaconda3\envs\server\lib\asyncio\base_events.py", line 587, in run_until_complete
return future.result()
File "D:/Python/server/client1.py", line 8, in message
print(await socket.recv())
File "C:\ProgramData\Anaconda3\envs\server\lib\site-packages\websockets\protocol.py", line 509, in recv
await self.ensure_open()
File "C:\ProgramData\Anaconda3\envs\server\lib\site-packages\websockets\protocol.py", line 812, in ensure_open
raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedOK: code = 1000 (OK), no reason
and this error from the server-side:
Task exception was never retrieved
future: <Task finished coro=<queue_dispatcher() done, defined at D:/RamNew2020/Python/server/asyncserver.py:39> exception=ConnectionClosedOK('code = 1000 (OK), no reason')>
Traceback (most recent call last):
File "D:/Python/server/asyncserver.py", line 45, in queue_dispatcher
await data_from_q.sendto_websocket("yay")
File "D:/Python/server/asyncserver.py", line 20, in sendto_websocket
await self.mywebsocket.send(message)
File "C:\ProgramData\Anaconda3\envs\server\lib\site-packages\websockets\protocol.py", line 555, in send
await self.ensure_open()
File "C:\ProgramData\Anaconda3\envs\server\lib\site-packages\websockets\protocol.py", line 803, in ensure_open
raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedOK: code = 1000 (OK), no reason
My scripts:
server.py:
import asyncio
import websockets
import datetime
import random
queue = asyncio.Queue()
async def rnd_sleep(t):
# sleep for T seconds on average
await asyncio.sleep(t * random.random() * 2)
#When a client sends a message the information is saved in a Request object,
#including the socket connection
class Request:
def __init__(self, mywebsocket, mydat):
self.mywebsocket = mywebsocket
self.mydat = mydat
self.start_time_of_request = datetime.datetime.now()
self.id = random.randint(0, 128)
async def sendto_websocket(self, message):
await self.mywebsocket.send(message)
def get_dat(self):
return self.mydat
def get_start_time(self):
return self.start_time_of_request
async def add_to_queue(websocket, path):
global queue
dat = await websocket.recv()
base64dat = Request(websocket, dat)
await queue.put(base64dat)
#problem in queue_dispatcher
async def queue_dispatcher(q):
while True:
data_from_q = await q.get()
print(data_from_q.id)
await asyncio.sleep(1) #The problem is here, whenever I remove it, it works
await data_from_q.sendto_websocket("yay")
q.task_done()
async def main():
global queue
asyncio.create_task(queue_dispatcher(queue))
pass
start_server = websockets.serve(add_to_queue, 'localhost', 5000)
asyncio.get_event_loop().run_until_complete(main())
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
client.py:
import asyncio
async def message():
async with websockets.connect("ws://localhost:5000")as socket:
msg = input("What do you want to send: ")
await socket.send(msg)
print(await socket.recv())
asyncio.get_event_loop().run_until_complete(message())
In addition, whenever I try to await any other async function, it works fine no matter how long.

Return results with asyncio

I have the following code:
async def get_balance(exchange, symbol='BTC/USD'):
freeBalance = await exchange.fetchBalance()
symbol1_balance = freeBalance[symbol.split('/')[0]]
symbol2_balance = freeBalance[symbol.split('/')[1]]
return symbol1_balance, symbol2_balance
async def get_balances(exchanges):
futures = [get_balance(exchange) for exchange in exchanges]
balances = await asyncio.gather(*futures)
return balances
exchanges = [exchange1, exchange2, ...]
loop = asyncio.get_event_loop()
results = loop.run_until_complete(get_balances(exchanges))
But I get the error:
res = loop.run_until_complete(get_balances(exchanges, symbol))
Traceback (most recent call last):
File "C:\Users\Nicolas\Anaconda3\lib\asyncio\base_events.py", line
570, in run_until_complete
self.run_forever()
File "C:\Users\Nicolas\Anaconda3\lib\asyncio\base_events.py", line
525, in run_forever
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
main:49: RuntimeWarning: coroutine 'binance.fetch_balance' was never awaited RuntimeWarning: Enable tracemalloc to get the object
allocation traceback
main:49: RuntimeWarning: coroutine 'bitfinex.fetch_balance' was never awaited RuntimeWarning: Enable tracemalloc to get the object
allocation traceback
To be clear:
print(exchanges[0].fetchBalance())
<coroutine object binance.fetch_ticker at 0x000001FE6473BA48>
So the function get_balance is already a coroutine.
I managed to run the first asyncio-example-gather except that instead of
asyncio.run(main())
File "C:\Users\Nicolas\Anaconda3\lib\asyncio\runners.py", line 34,
in run
"asyncio.run() cannot be called from a running event loop")
RuntimeError: asyncio.run() cannot be called from a running event loop
But the following works:
loop = asyncio.get_running_loop()
res = loop.create_task(main())
I am pretty knew with asynchronous programming, was more using multithreading before. Do you know what's wrong here please?
Thank you guys!

Categories

Resources