2

So, I don't seem to find any good tutorial on using the new asyncio module in python (async, await, etc.). Also, from all the tutorials I've watched, the concept is poorly described and I don't seem to be able to wrap my head around the idea of coroutines. I mean, the idea behind the concept is not that hard, but there's not a single place where I can learn exactly what the coroutines can and cannot do, and how to use them.

For example, I have written a small class called YouTubeAPI for a Discord BOT that I'm building at the moment. The Discord.py library uses asyncio for all its functions, but my class doesn't. My class (YouTubeAPI) is made for the sole purpose of retrieving data from the YouTube Data API V3 about latest videos posted by a user. I'm actually trying to build a BOT that keeps me up-to-date on all the videos someone is posting.

But for the BOT to be working I need to make an update() function that gets all the videos regularly so that I can get the latest video. The problem is that the update function needs to be wrapped in a while True loop (or something similar), so that I can keep the list up-to-date. If I build an infinite loop then I'm gonna run into a problem with the BOT (making the BOT crash and unusable).

So, I thought maybe I could learn the new asyncio module and solve the problem that way. Sadly I find nothing.

Here's some code with all the API keys removed, so that you can see my problem easier:

from Api_Test import YoutubeAPI
import discord
import asyncio

YoutubeName = 'Vsauce'
GOOGLE_API = 'API KEY'

print('Collecting YouTube Data.')
api = YoutubeAPI(GOOGLE_API, YoutubeName) # create object that will get all info for the name 'Vsauce'
print('YouTube Data collected succesfully.')
print('Starting bot.')

def getLastVideo():
    return api.videosData[0] # api.videosData looks like: [[title, link],[title, link],[title, link],]

client = discord.Client()

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')
    await client.send_message('Now testing: Last {} videos!'.format(YoutubeName))


#While Loop that keeps the api.videosData up-to-date and runs "await client.send_message('new video: title + ink')" if new video found in the list

client.run('Discord BOT token')

I am extremely sorry if this post sounds vaguely explained, but I have totally no idea on how to use asyncio or something similar and I find myself in a place where I find almost no documentation on this new concept.

boardrider
  • 5,882
  • 7
  • 49
  • 86
Brian Briu
  • 45
  • 5
  • This might help: [asyncio user documentation](http://asyncio.readthedocs.io/en/latest/). – Vincent Feb 09 '17 at 21:35
  • Try https://stackoverflow.com/questions/41785617/python-asyncio-task-ordering, http://lucumr.pocoo.org/2016/10/30/i-dont-understand-asyncio/​, and https://community.nitrous.io/tutorials/asynchronous-programming-with-python-3. – boardrider Feb 10 '17 at 11:14

3 Answers3

2

You can use ensure_future() to run your while loop. Here the loop starts when on_ready is called and runs until the bot is shut down

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')
    await client.send_message('Now testing: Last {} videos!'.format(YoutubeName))

    asyncio.ensure_future(update_data(), client.loop) # Starts the infinite loop when the bot starts

async def update_data():
    while True:
        # Do the things you need to do in this loop
        await asyncio.sleep(1) # sleep for 1 second

client.run('Discord BOT token')
s0hvaperuna
  • 56
  • 1
  • 5
0

You can run a function (like something to retrieve your data from Youtube) via asyncio.ensure_future in the background

An example from my own bot:

games = [
    'try :help',
    'with Atom.io',
    'with Python',
    'HuniePop'
]

async def randomGame():
    while True:
        await bot.change_presence(game=discord.Game(name=random.choice(games)))
        await asyncio.sleep(10*60) # 10 Minutes

and

@client.event
async def on_ready():
    print('Logged in as')
    print('Bot-Name: {}'.format(bot.user.name))
    print('Bot-ID: {}'.format(bot.user.id))
    ...
    bot.gamesLoop = asyncio.ensure_future(randomGame())

More informations about this can be found here: https://docs.python.org/3/library/asyncio-task.html

Der-Eddy
  • 763
  • 10
  • 12
  • But where do you actually run the client.run () function? Because you can't run it in the loop. That way you wojld make the bot crash. Or am I wrong? – Brian Briu Feb 10 '17 at 06:40
0

But where do you actually run the client.run () function? Because you can't run it in the loop. That way you wojld make the bot crash. Or am I wrong?

client.run("token")

is always on the last line of a Discord.PY bot, as soon as the function takes place the bot is constantly running until a client.close() function takes place, or the environment is closed.

ocelot
  • 1,067
  • 12
  • 16