I am trying to make a rank card using PIL and discord.py UPDATED - discord.py

i have a leveling system, using discord.py, i am trying to make a rank card, like mee6 and arcane. i wanna get the image to display the users rank and xp
heres the command that works, but i want to make it into a image.
#bot.command(aliases = ['rank','lvl'])
async def level(ctx,member: discord.Member = None):
if not member:
user = ctx.message.author
with open('level.json','r') as f:
users = json.load(f)
lvl = users[str(ctx.guild.id)][str(user.id)]['level']
exp = users[str(ctx.guild.id)][str(user.id)]['experience']
embed = discord.Embed(title = 'Level {}'.format(lvl), description = f"{exp} XP " ,color = discord.Color.green())
embed.set_author(name = ctx.author, icon_url = ctx.author.avatar_url)
await ctx.send(embed = embed)
else:
with open('level.json','r') as f:
users = json.load(f)
lvl = users[str(ctx.guild.id)][str(member.id)]['level']
exp = users[str(ctx.guild.id)][str(member.id)]['experience']
embed = discord.Embed(title = 'Level {}'.format(lvl), description = f"{exp} XP" ,color = discord.Color.green())
embed.set_author(name = member, icon_url = member.avatar_url)
await ctx.send(embed = embed)
and heres my crappy atempt.
#bot.command()
async def text(ctx):
text = [f"level {lvl}, exp {exp}"]
user = ctx.message.author
img = Image.open("rank.jpg")
with open('level.json','r') as f:
users = json.load(f)
lvl = users[str(ctx.guild.id)][str(user.id)]['level']
exp = users[str(ctx.guild.id)][str(user.id)]['experience']
text = ['Level {}'.format(lvl)]
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("font.ttf", 150)
draw.text((480,445), text, (0, 0, 0,), font=font)
img.save("rankcard.jpg")
await ctx.send(file = discord.File("rankcard.jpg"))
and heres the console error, i doubt theres only one error with my code
Ignoring exception in command text:
Traceback (most recent call last):
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "C:\Users\Jack\Desktop\just some code\bot.py", line 33, in text
text = [f"level {lvl}, exp {exp}"]
UnboundLocalError: local variable 'lvl' referenced before assignment
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: UnboundLocalError: local variable 'lvl' referenced before assignment
if you could fix up the code for me. i would be ever so greatful.
-thanks
UPDATE: i have now sorted those issues out but still trying to figure this out, my code:
#bot.command()
async def test(ctx,member: discord.Member = None):
global lvl, exp
if not member:
user = ctx.message.author
with open('level.json','r') as f:
users = json.load(f)
img = Image.open("rank.jpg")
lvl = users[str(ctx.guild.id)][str(user.id)]['level']
exp = users[str(ctx.guild.id)][str(user.id)]['experience']
text = [f"level {lvl}, exp {exp}"]
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("font.ttf", 150)
draw.text((480,445), text, (0, 0, 0,), font=font)
img.save("rankcard.jpg")
await ctx.send(file = discord.File("rankcard.jpg"))
and my error:
Traceback (most recent call last):
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: expected string

You have to firstly define lvl and exp in the text function or global it as this is not found.
#bot.command()
async def text(ctx):
lvl = ...
exp = ...
text = [f"level {lvl}, exp {exp}"]
user = ctx.message.author
OR
#bot.command(aliases = ['rank','lvl'])
async def level(ctx,member: discord.Member = None):
global lvl, exp
if not member:
user = ctx.message.author
with open('level.json','r') as f:

Related

sys:1: RuntimeWarning: coroutine 'AirthingsWaveDetect.get_sensors' was never awaited

I am a beginner trying to get the data from airthings plus to hubitat using a raspberry pi. When running a python script I get this error message :
readwaveplus.py:391: RuntimeWarning: coroutine 'AirthingsWaveDetect.get_sensor_data' was never awaited
data = airthingsdetect.get_sensor_data()[MAC]
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Read Error
^CTraceback (most recent call last):
File "readwaveplus.py", line 414, in <module>
time.sleep(SamplePeriod)
KeyboardInterrupt
sys:1: RuntimeWarning: coroutine 'AirthingsWaveDetect.get_sensors' was never awaited
It seems I need to add "await" somewhere but I am not able to figure out where. I tried to add await but not sure where It should be added.
Here is the script :
async def main():
logging.basicConfig()
_LOGGER.setLevel(logging.DEBUG)
ad = AirthingsWaveDetect(0)
num_dev_found = await ad.find_devices()
if num_dev_found > 0:
devices = await ad.get_info()
for mac, dev in devices.items():
_LOGGER.info("Device: {}: {}".format(mac, dev))
devices_sensors = await ad.get_sensors()
for mac, sensors in devices_sensors.items():
for sensor in sensors:
_LOGGER.info("Sensor: {}: {}".format(mac, sensor))
sensordata = await ad.get_sensor_data()
for mac, data in sensordata.items():
for name, val in data.items():
_LOGGER.info("Sensor data: {}: {}: {}".format(mac, name, val))
if __name__ == "__main__":
asyncio.run(main())
import time
import requests
# The period between two measurements in seconds (Default: 300)
SamplePeriod = 300
MAC = 'd8:71:4d:ca:de:dc'
# The hostname or IP address of the MQTT broker Hubitat hub to connect
makerAPIHostname = "192.168.1.38"
makerAPIAppID = "2416"
makerAPIToken = "8ca5e2ac-7d0b-4c24-a89b-f6022844e2ae"
makerAPIDeviceID = "AirThings Wave Plus"
from airthings import AirthingsWaveDetect
scan_interval = 120
airthingsdetect = AirthingsWaveDetect(scan_interval, MAC)
V_MAX = 3.0
V_MIN = 2.0
#---- Initialize ----#
URL = "http://{}/apps/api/{}/devices/{}/{}?access_token={}".format(makerAPIHostname, makerAPIAppID, makerAPIDeviceID, '{}/{}', makerAPIToken)
devices_sensors = airthingsdetect.get_sensors()
while True:
try:
data = airthingsdetect.get_sensor_data()[MAC]
except:
print( 'Read Error' )
pass
else:
sensorData = "{},{},{},{},{},{},{},{},{}".format(
data['temperature'],
data['humidity'],
data['rel_atm_pressure'],
data['co2'],
data['voc'],
round(data['radon_1day_avg']/37.,2),
round(data['radon_longterm_avg']/37.,2),
max(0, min(100, round( (data['battery']-V_MIN)/(V_MAX-V_MIN)*100))),
round(data['illuminance'])
)
#print( sensorData )
try:
request = URL.format('setValues', sensorData)
requests.get(request)
except:
pass
finally:
time.sleep(SamplePeriod)
Any idea ? Thanks.
Async needs an await but I don't know where. Thanks.

Discord.py How to make a if this fail function

Hi I have following code
#commands.command(name="playing", aliases=["np"])
async def playing_command(self, ctx, name: t.Optional[str]):
player = self.get_player(ctx)
name = name or player.queue.current_track.title
async with ctx.typing():
async with aiohttp.request("GET", LYRICS_URL + name, headers={}) as r:
#if not 200 <= r.status <= 299:
#raise NoLyricsFound
data = await r.json()
if not player.is_playing:
raise PlayerIsAlreadyPaused
embed = discord.Embed(
title="Wird gespielt",
colour=ctx.author.colour,
timestamp=dt.datetime.utcnow(),
)
embed.set_thumbnail(url=data["thumbnail"]["genius"])
embed.set_footer(text=f"Requested by {ctx.author.display_name}", icon_url=ctx.author.avatar_url)
embed.add_field(name="Track title", value=player.queue.current_track.title, inline=False)
embed.add_field(name="Artist", value=player.queue.current_track.author, inline=False)
position = divmod(player.position, 60000)
length = divmod(player.queue.current_track.length, 60000)
embed.add_field(
name="Position",
value=f"{int(position[0])}:{round(position[1]/1000):02}/{int(length[0])}:{round(length[1]/1000):02}",
inline=False
)
await ctx.send(embed=embed)
But when I run this and the bot cant find a Thumbnail I get the key Error 'thumbnail'
So I tried this
#playing_command.error
async def playing_command(self, ctx, name: t.Optional[str]):
player = self.get_player(ctx)
name = name or player.queue.current_track.title
async with ctx.typing():
async with aiohttp.request("GET", LYRICS_URL + name, headers={}) as r:
#if not 200 <= r.status <= 299:
#raise NoLyricsFound
data = await r.json()
if not player.is_playing:
raise PlayerIsAlreadyPaused
embed = discord.Embed(
title="Wird gespielt",
colour=ctx.author.colour,
timestamp=dt.datetime.utcnow(),
)
embed.set_footer(text=f"Requested by {ctx.author.display_name}", icon_url=ctx.author.avatar_url)
embed.add_field(name="Track title", value=player.queue.current_track.title, inline=False)
embed.add_field(name="Artist", value=player.queue.current_track.author, inline=False)
position = divmod(player.position, 60000)
length = divmod(player.queue.current_track.length, 60000)
embed.add_field(
name="Position",
value=f"{int(position[0])}:{round(position[1]/1000):02}/{int(length[0])}:{round(length[1]/1000):02}",
inline=False
)
await ctx.send(embed=embed)
But with this I get errors like
_ClientEventTask exception was never retrieved
future: <ClientEventTask state=finished event=on_message coro=<bound method MusicBot.on_message of <bot.bot.MusicBot object at 0x0000022FEF05E6A0>> exception=CommandInvokeError('Command raised an exception: TypeError: can only concatenate str (not "CommandInvokeError") to str')>
Traceback (most recent call last):
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "C:\Users\user\Desktop\Neuer Ordner\MusicBot\bot\cogs\music.py", line 637, in playing_command
embed.set_thumbnail(url=data["thumbnail"]["genius"])
KeyError: 'thumbnail'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: KeyError: 'thumbnail'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 71, in wrapped
ret = await coro(*args, **kwargs)
File "C:\Users\user\Desktop\Neuer Ordner\MusicBot\bot\cogs\music.py", line 658, in error_command
async with aiohttp.request("GET", LYRICS_URL + name, headers={}) as r:
TypeError: can only concatenate str (not "CommandInvokeError") to str
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 348, in _run_event
await self.on_error(event_name, *args, **kwargs)
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "C:\Users\user\Desktop\Neuer Ordner\MusicBot\bot\bot.py", line 68, in on_message
await self.process_commands(msg)
File "C:\Users\user\Desktop\Neuer Ordner\MusicBot\bot\bot.py", line 64, in process_commands
await self.invoke(ctx)
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 943, in invoke
await ctx.command.dispatch_error(ctx, exc)
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 422, in dispatch_error
await injected(cog, ctx, error)
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 77, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: can only concatenate str (not "CommandInvokeError") to str
How to fix this
I just want when the thumbnail function fails that the bot send a embed without thumbnail
To check if a key exists in a dict you can use the in operator.
>>> "key" in {"key": "value"}
True
So just put an if around the set_thumbnail line.
if "thumbnail" in data and "genius" in data["thumbnail"]:
embed.set_thumbnail(url=data["thumbnail"]["genius"])
If the if's condition is False it won't run set_thumbnail so it won't add one, like you wanted.

Ignoring exception in command buy

An error pops up when I do the buy command. This code comes from The coding academy discord server but they didn't seem to know how to help. This is for a currency bot. Here is my code followed by the error:
`mainshop = [{"name":"Knife","price":65,"description":"Mug people! Unlocks `mug`"},
{"name":"Laptop","price":5000,"description":"Post some sweet memes on reddit! Unlocks `postmemes`"},
{"name":"Gun","price":10000,"description":"Rob people and businesses! Unlocks `rob` and `mug`"}]
#client.command()
async def shop(ctx):
em = discord.Embed(title = "Shop")
for item in mainshop:
name = item["name"]
price = item["price"]
desc = item["description"]
em.add_field(name = name, value = f"${price} | {desc}")
await ctx.send(embed = em)
#client.command()
async def buy(ctx,item,amount = 1):
await open_account(ctx.author)
res = await buy_this(ctx.author,item,amount)
if not res[0]:
if res[1]==1:
await ctx.send("That Object isn't there!")
return
if res[1]==2:
await ctx.send(f"You don't have enough money in your wallet to buy {amount} {item}")
return
await ctx.send(f"You just bought {amount} {item}")
#client.command()
async def inventory(ctx):
await open_account(ctx.author)
user = ctx.author
users = await get_bank_data()
try:
bag = users[str(user.id)]["bag"]
except:
bag = []
em = discord.Embed(title = "Inventory")
for item in bag:
name = item["item"]
amount = item["amount"]
em.add_field(name = name, value = amount)
await ctx.send(embed = em)
async def buy_this(user,item_name,amount):
item_name = item_name.lower()
name_ = None
for item in mainshop:
name = item["name"].lower()
if name == item_name:
name_ = name
price = item["price"]
break
if name_ == None:
return [False,1]
cost = price*amount
users = await get_bank_data()
bal = await update_bank(user)
if bal[0]<cost:
return [False,2]
try:
index = 0
t = None
for thing in users[str(user.id)]["bag"]:
n = thing["item"]
if n == item_name:
old_amt = thing["amount"]
new_amt = old_amt + amount
users[str(user.id)]["bag"][index]["amount"] = new_amt
t = 1
break
index+=1
if t == None:
obj = {"item":item_name , "amount" : amount}
users[str(user.id)]["bag"].append(obj)
except:
obj = {"item":item_name , "amount" : amount}
users[str(user.id)]["bag"] = [obj]
with open("mainbank.json","w") as f:
json.dump(users,f)
await update_bank(user,cost*-1,"wallet")
return [True,"Worked"]
Error:
Ignoring exception in command buy: Traceback (most recent call last): File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs) File "main.py", line 50, in buy
res = await buy_this(ctx.author,item,amount) File "main.py", line 104, in buy_this
if bal[0]<cost: TypeError: 'bool' object is not subscriptable
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 902, in invoke
await ctx.command.invoke(ctx) File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs) File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: 'bool' object is not subscriptable
As much as I see your value of the variable bal is somehow a bool value due to which if you try to take out values from it as a list, it gives you the following error.
You should try checking the definition of the update_bank() command and check it's return type.
Check this website for more info on the error : https://www.tutorialexample.com/fix-typeerror-bool-object-is-not-subscriptable-in-python-python-tutorial/

When streaming tweets with Python Twitter I get the error message: OpenSSL.SSL.SysCallError: (104, 'ECONNRESET')

I got this error where I have no clue where it come from and where to start to debug. I do not understand this error at all. I'll just post my code here. I utilized multithreading in my code to periodically save the tweets on separate files. My program will work fine for maybe over 10 days, and then throw me this error message. Maybe twitter reset my connection?
import twitter
import json
import time
from tqdm import tqdm
import string
from datetime import timedelta, datetime
import threading
import os
consumer_key = '*'
consumer_secret = '*'
access_token_key = '*'
access_token_secret = '*'
api = twitter.Api(consumer_key = consumer_key,\
consumer_secret = consumer_secret,\
access_token_key = access_token_key,\
access_token_secret = access_token_secret)
os.chdir('*/social_media/streamed_tweets')
#multiThreading class and functions starts here
class timerThread(threading.Thread):
def __init__(self, threadID, name, stoptime, stopevent): #remember to change args accordingly
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.stoptime = stoptime
self.stopevent = stopevent
def run(self):
print("Starting " + self.name)
twiTimer(self.stoptime, self.stopevent)
print("Exiting " + self.name)
class streamerThread(threading.Thread):
def __init__(self, threadID, name, keywords, stop): #remember to change args accordingly
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.keywords = keywords
self.stop = stop
def run(self):
print("Starting " + self.name)
twiStream(self.keywords, self.stop)
print("Exiting " + self.name)
def twiTimer(stop_time, stop_event):
while True:
now1 = datetime.now()
t = str(now1.timetz())
if t[:8] == stop_time: #make it t[:8] for daily loop
stop_event.set()
print('stop triggered')
time.sleep(1) #wait to pass the '00' time
time.sleep(0.1)
def twiStream(keywords, stop_event):
while True:
stream = api.GetStreamFilter(track = keywords, languages=['en'], filter_level = None)
now2 = datetime.now()
filename = str(now2.date())+'.txt' #change this to date() for daily loop
f = open(filename, 'w+')
stop_event.clear() #reset the event
print(now2)
with tqdm() as pbar:
while not stop_event.is_set():
counter = 2
for tweet in stream:
if counter <= 0:
break
f.write(json.dumps(tweet))
f.write('\n')
pbar.update()
counter -= 1
f.close()
time.sleep(0.5)
#multiThreading class and functions ends here
def main():
keywords = ['*']
stop = threading.Event()
stop_at = '00:00:00' #make it '00:00:00' for daily loop
#count = 10
thread1 = timerThread(1, 'timerThread', stop_at, stop)
thread2 = streamerThread(2, 'streamerThread', keywords, stop)
thread1.start()
thread2.start()
print("Exiting Main Thread")
if __name__ == "__main__":
main()
Here is the full error message:
Exception in thread streamerThread:
Traceback (most recent call last):
File "/home/abe/anaconda3/lib/python3.6/site-packages/urllib3/contrib/pyopenssl.py", line 285, in recv_into
return self.connection.recv_into(*args, **kwargs)
File "/home/abe/anaconda3/lib/python3.6/site-packages/OpenSSL/SSL.py", line 1814, in recv_into
self._raise_ssl_error(self._ssl, result)
File "/home/abe/anaconda3/lib/python3.6/site-packages/OpenSSL/SSL.py", line 1631, in _raise_ssl_error
raise SysCallError(errno, errorcode.get(errno))
OpenSSL.SSL.SysCallError: (104, 'ECONNRESET')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/abe/anaconda3/lib/python3.6/site-packages/urllib3/response.py", line 331, in _error_catcher
yield
File "/home/abe/anaconda3/lib/python3.6/site-packages/urllib3/response.py", line 637, in read_chunked
self._update_chunk_length()
File "/home/abe/anaconda3/lib/python3.6/site-packages/urllib3/response.py", line 569, in _update_chunk_length
line = self._fp.fp.readline()
File "/home/abe/anaconda3/lib/python3.6/socket.py", line 586, in readinto
return self._sock.recv_into(b)
File "/home/abe/anaconda3/lib/python3.6/site-packages/urllib3/contrib/pyopenssl.py", line 290, in recv_into
raise SocketError(str(e))
OSError: (104, 'ECONNRESET')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/abe/anaconda3/lib/python3.6/site-packages/requests/models.py", line 749, in generate
for chunk in self.raw.stream(chunk_size, decode_content=True):
File "/home/abe/anaconda3/lib/python3.6/site-packages/urllib3/response.py", line 461, in stream
for line in self.read_chunked(amt, decode_content=decode_content):
File "/home/abe/anaconda3/lib/python3.6/site-packages/urllib3/response.py", line 665, in read_chunked
self._original_response.close()
File "/home/abe/anaconda3/lib/python3.6/contextlib.py", line 99, in __exit__
self.gen.throw(type, value, traceback)
File "/home/abe/anaconda3/lib/python3.6/site-packages/urllib3/response.py", line 349, in _error_catcher
raise ProtocolError('Connection broken: %r' % e, e)
urllib3.exceptions.ProtocolError: ('Connection broken: OSError("(104, \'ECONNRESET\')",)', OSError("(104, 'ECONNRESET')",))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/abe/anaconda3/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "streamer.py", line 48, in run
twiStream(self.keywords, self.stop)
File "streamer.py", line 72, in twiStream
for tweet in stream:
File "/home/abe/anaconda3/lib/python3.6/site-packages/twitter/api.py", line 4575, in GetStreamFilter
for line in resp.iter_lines():
File "/home/abe/anaconda3/lib/python3.6/site-packages/requests/models.py", line 793, in iter_lines
for chunk in self.iter_content(chunk_size=chunk_size, decode_unicode=decode_unicode):
File "/home/abe/anaconda3/lib/python3.6/site-packages/requests/models.py", line 752, in generate
raise ChunkedEncodingError(e)
requests.exceptions.ChunkedEncodingError: ('Connection broken: OSError("(104, \'ECONNRESET\')",)', OSError("(104, 'ECONNRESET')",))

Can't exit asynchronous process

I have a problem with the exiting from the asynchronous process which is handled by asyncio. This is the ftp server + client project and I want to kill the client process after 'exit' command.
The most important part of this code is here:
class FtpCommandsReceiver:
def __init__(self, loop, sock):
self.loop = loop
self.sock = sock
self.loop.create_task(self.recieve_data())
self.commands_to_handle = {
'exit': self.exit_handler
}
async def recieve_data(self):
while True:
self.data_to_send = input('ftp> ')
if self.data_to_send == '':
continue
await self.loop.sock_sendall(self.sock, self.data_to_send.encode())
try:
await self.commands_to_handle.get(self.data_to_send)()
except TypeError:
pass
self.received_data = await self.loop.sock_recv(self.sock, 10000)
print(self.received_data.decode())
if not self.received_data:
break
print('Connection closed by the server')
self.sock.close()
async def exit_handler(self):
self.loop.stop()
self.loop.close()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
FTP_connection = FtpConnection(loop)
task = loop.create_task(FTP_connection.connect())
try:
loop.run_forever()
finally:
loop.close()
When it calls exit_handler method, the exception raises:
Task exception was never retrieved
future: exception=RuntimeError('Cannot close a running event loop',)>
Traceback (most recent call last):
File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
result = coro.send(None)
File "FTPclient.py", line 54, in recieve_data
await self.commands_to_handle.get(self.data_to_send)()
File "FTPclient.py", line 66, in exit_handler
self.loop.close()
File "/usr/lib/python3.5/asyncio/unix_events.py", line 56, in close
super().close()
File "/usr/lib/python3.5/asyncio/selector_events.py", line 94, in close
raise RuntimeError("Cannot close a running event loop")
RuntimeError: Cannot close a running event loop
I will be grateful for your help and thank you in advance!

Resources