2

I am using Tkinter and discord.py together, and I want it to change the user's nickname on the press of a button. to change the nickname, discord.py uses the command yield from client.change_nickname(server.me, string) but when I run that code in the command of a button, the function never get's ran. I have used a print statement to make sure, and none of the function gets ran. I have tried to use multi-threading to start the function, and that didn't work, any help would be appreciated

async def test2():
    server = client.get_server("345548250432012298")
    await client.change_nickname(server.me, "testing")
def test():
    threading.Thread(target=test2).start()
def makeThing(nicks):
    frame = Tk()
    for i in range(0, len(nicks)):
        Button(frame, text=nicks[i], command= test).grid(row=i)
    frame.mainloop()
Tyler Silva
  • 411
  • 6
  • 14

1 Answers1

0

Your problem is that you're trying to call an async def coroutine using the threading module. To make this work, you'll need to use asyncio to run an event loop in your test function. Assuming you don't care about the implications of a long-running call in your main thread, you can just directly use run_until_complete.

import asyncio

async def test2():
    server = client.get_server("345548250432012298")
    await client.change_nickname(server.me, "testing")
def test():
    loop = asyncio.get_event_loop()  
    loop.run_until_complete(test2())
    loop.close()  
def makeThing(nicks):
    frame = Tk()
    for i in range(0, len(nicks)):
        Button(frame, text=nicks[i], command= test).grid(row=i)
    frame.mainloop()

If you need to make more async calls in one event loop, use ensure_future instead. Do note that you can break the async call off into its own thread using threading (as you correctly surmised) as long as you call the run_until_complete in the thread.

This answer should help you use threads with asyncio (in that answer, @asyncio.coroutine is generally equivalent to async def but there do exist some differences) and this async/await tutorial should serve you well for general learning.

Peter G
  • 2,773
  • 3
  • 25
  • 35
  • 1
    this works slightly better, but i am getting the error "RuntimeError: This event loop is already running" this is the only asyncio function i am calling. it may be discord.py using an event loop. i tried putting it into a seperate thread, and got the same error. i dont know where i would put the "ensure future" command – Tyler Silva Oct 04 '17 at 20:28
  • @TylerSilva You're right, they do have their own event loop. I'll edit this in a little bit but you should use `client.loop.create_task` to use their event loop (`client.loop` if you'd prefer to just have the loop) source: https://github.com/Rapptz/discord.py/blob/master/examples/background_task.py – Peter G Oct 04 '17 at 20:51
  • now it doesnt change the nickname until after i close the tkinter window. there are no errors, just waits until you xit out of the tkinter window to run the code – Tyler Silva Oct 04 '17 at 21:10