Issue
I know that I shouldn't use exec
because it's insecure but the code it run comes from the same file and is a string. How can I use exec
to run an async function? It always returns me SyntaxError: 'await' outside function
if I try it.
Edit: This is the Code where I am using exec
:
async def command_processor(guild):
while True:
commands = {"[1] - Bot Permissions abrufen" : "print_permissions(guild)",
"Derzeit nicht verwendbar - [2] - Invite zu Gilde erstellen (max Nutzungen pro Invite: 1)" : "await print_invite(guild)",
"[3] - Gebannte Benutzer auflisten (benötigt Berechtigung {Mitglieder bannen}" : "print_banned(guild)",
"[4] - Ausgewählten Server wechseln" : "change_guild()",
"[5] - Ausgewählten Bot wechseln" : "change_bot()",
"[6] - Beenden" : "sys.exit()"
}
print("\n\n--------------- Befehle ---------------\n")
for i in range(len(commands.keys())):
print(list(commands.keys())[i])
sel = input()
print()
try:
int(sel)
except:
print("Bitte hier nur die Zahl eingeben")
if int(sel) in range(len(commands.keys())):
exec(list(commands.values())[int(sel)-1])
Solution
You could do this, I think. The problem with exec
is that it doesn't return anything, so you would need to use eval
instead. I think this could work:
async def command_processor(guild):
while True:
commands = {"[1] - Bot Permissions abrufen" : "print_permissions(guild)",
"Derzeit nicht verwendbar - [2] - Invite zu Gilde erstellen (max Nutzungen pro Invite: 1)" : "await print_invite(guild)",
"[3] - Gebannte Benutzer auflisten (benötigt Berechtigung {Mitglieder bannen}" : "print_banned(guild)",
"[4] - Ausgewählten Server wechseln" : "change_guild()",
"[5] - Ausgewählten Bot wechseln" : "change_bot()",
"[6] - Beenden" : "sys.exit()"
}
# ...
if int(sel) in range(len(commands.keys())):
await eval(list(commands.values())[int(sel)-1])
But there's no need to use eval
here, and you have a lot to lose. A simple way could be to use a dict, something along the lines:
commands = {1: {"description": "[1] - Bot Permission abrufen", "command" : print_permissions, "args": [guild]},
# ...
}
for cmd in commands:
print(cmd['description'])
# ...
selected_command = commands[sel]
await selected_command['command'](*selected_command['args'])
But it gets tricky, since sometimes you have a coroutine and sometimes a regular method. To get around that, I guess you could do this:
commands = {
1: {"description": "[1] - Bot Permission abrufen", "exec" : print_permissions, "args": [guild]},
2: {"description": "Derzeit nicht verwendbar - [2] - Invite zu Gilde erstellen (max Nutzungen pro Invite: 1)", "exec": print_invite, "args": [guild]},
# ...
}
for cmd in commands:
print(cmd['description'])
# ...
selected_command = commands[sel]
if asyncio.iscoroutinefunction(selected_command['exec']):
await selected_command['exec'](*selected_command['args'])
else:
selected_command['exec'](*selected_command['args'])
On a final note: It make's me nervous that we now have the key that needs to pressed in two different places. This will lead to tears in the end, mark my words. I would do something like this:
commands = [
{
"description": "[{keynum}] - Bot Permission abrufen",
"exec" : print_permissions, "args": [guild]
},
{
"description": "Derzeit nicht verwendbar - [{keynum}] - Invite zu Gilde erstellen (max Nutzungen pro Invite: 1)",
"exec": print_invite, "args": [guild]
},
]
for keynum, command in enumerate(commands):
print(command['description'].format(keynum=keynum))
I haven't tested that code, so there's probably a bug, but you get the idea.
Answered By - obeq
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.