Whenever i try to make a Chatbot
I choose to use endpoint
But i get this error
File "/app/chatbot/plugins/response.py", line 10
print((await get_response('world')))
^
SyntaxError: 'await' outside function
Please help me i would be highly obliged if you help me
Where my code is
import aiohttp
async def get_response(query):
async with aiohttp.ClientSession() as ses:
async with ses.get(
f'https://some-random-api.ml/chatbot?message={query}'
) as resp:
return (await resp.json())['response']
print((await get_response('world')))
Solution:
await is used in an async functions/methods to wait on other asynchronous tasks, but if you are calling an async function/method outside of an async function/method you need to use asyncio.run() method to call an async function/method
Here is the full solution:
import aiohttp
import asyncio #to run async funtions you need to import asyncio
async def get_response(query):
async with aiohttp.ClientSession() as ses:
async with ses.get(
f'https://some-random-api.ml/chatbot?message={query}'
) as resp:
return (await resp.json())['response']
print((asyncio.run( get_response('world')))#run the async function
Related
here is the problem:
async def init():
loop = asyncio.get_event_loop()
loop.run_until_complete(main(sessions, message))
async def main(sessions, message):
# some code to execute...
i'am trying to run the function main(sessions, message) in run_until_complete, but the problem is that I cannot get the coroutine in an async function, because is it throws an error that: RuntimeWarning: coroutine 'main' was never awaited
can you tell me please how should i run a function like that correctly?
You don’t need to use run_until_complete inside a coroutine. The way you wait for something to finish inside a coroutine is to await it.
async def init():
await main(sessions, message)
Just do
import asyncio
async def init():
await main(...)
async def main(sessions, message):
...
loop = asyncio.get_event_loop()
loop.run_until_complete(init())
async def get_guild_members(guild_id: int):
guild = bot.fetch_guild(guild_id)
return guild.member_count
get_guild_members(789226204980707409)
I'm using this code to try to find the memeber count of a guild on discord. WHen I run it it returns
<coroutine object get_guild_members at 0x7ffd518ef4c0>
What does this mean? How do I do it correctly?
This problem stems from your lack of knowledge of asyncio. You don't call asynchronous functions like regular functions but rather use asyncio.run(coro()) or the await coro() syntax inside another async function.
REGULAR FUNCTION
def main():
pass
main()
ASYNCIO FUNCTION
import asyncio
async def get_guild_members(guild_id: int):
guild = await bot.fetch_guild(guild_id)
return guild.member_count
member_count = asyncio.run(get_guild_members(78922624980707409))
This question already has an answer here:
SyntaxError (Python): 'await' outside async function
(1 answer)
Closed 1 year ago.
I know - there are a lot of questions with this title, but most are for Dark Sky or are different to my problem.
class Counter(discord.ui.View):
#discord.ui.button(label='0', style=discord.ButtonStyle.red)
async def counter(self, button: discord.ui.Button, interaction:
discord.Interaction):
number = int(button.label)
button.label = str(number + 1)
if number + 1 >= 5:
button.style = discord.ButtonStyle.green
await interaction.message.edit(view=self)
view = Counter()
await ctx.send('Press to increment', view=view)
Error message:
File "main.py", line 27
await ctx.send('Press to increment', view=view)
^
SyntaxError: 'await' outside function
I'm very new to python and am not sure why this is at all. Any help would be greatly appreciated!
you need to put the
view = Counter()
await ctx.send('Press to increment', view=view)
code inside a asynchron function, because the await keyword can only be used inside of asynchron functions.
example functions
async def my_function(): # this is an async function
...
def my_other_function(): # this is a normal function
...
Async functions have to be called with the await keyword, or else you'll get an exception
await my_function() # calling an async function
my_other_function() # calling a normal function
as you can see in this example, in the async function, you can use await
async def something():
print("hello async world")
async def my_function():
await something()
but if you try to await an async function inside a normal function
asnyc def something():
print("hello async world")
def my_other_function():
await something()
You will get the SyntaxError: 'await' outside function error
The best way to do this together with a discord bot is by adding the code to a listener. For example with the on_message event which will be fired whenever a message is incoming
Example for on_message event
import discord
client = discord.Client()
#client.event
async def on_message(message): # The event
if message.content == "your_text" # Insert a text here that is needed to use the "command"
# your code will be executed whenever the bot receives a message with the content "your_text"
view = Counter()
await message.channel.send('Press to increment', view=view)
client.run("your unique token here")
I would recommend to take a look at https://discordpy.readthedocs.io/en/stable/quickstart.html before starting
According to the ctx, your code is made for the client's #commands.command function.
(this should fix your code)
from discord.ext import commands
bot = commands.Bot(command_prefix="!")
class Counter(discord.ui.View):
#discord.ui.button(label='0', style=discord.ButtonStyle.red)
async def counter(self, button: discord.ui.Button, interaction:
discord.Interaction):
number = int(button.label)
button.label = str(number + 1)
if number + 1 >= 5:
button.style = discord.ButtonStyle.green
await interaction.message.edit(view=self)
#bot.command("test")
async def command(ctx):
view = Counter()
await ctx.send('Press to increment', view=view)
bot.run("your unique token here")
In order to use your code, you need to send a message in a channel where your bot can read messages with the content !test to invoke the command
The typical structure of your code will be (using sample code from the docs)
#bot.command()
async def foo(ctx, arg):
await ctx.send(arg)
That's also where the ctx you're using comes from--if you removed the await you'd get an error that ctx wasn't defined. Your code will specify functions that correspond to commands or other events on discord, and discord.py will handle calling the functions you specify when users perform those actions.
You can only use the await keyword in async functions. The idea behind these functions is that if your code has to do something that takes a long time, but mostly just involves waiting, python can go do other stuff while it waits. For discord.py, since a lot of your operations involve waiting for slow network operations like sending messages, that's very important.
here's one intro to the ideas behind async/await, I haven't read it too much, so if it's bad or anybody has better suggestions drop a link in the comments.
I am trying to use use grequests to make a single HTTP call asynchronously.
All goes find until I try to call a function (handle_cars) to handle the response.
The problem is that the function is an async function and it I don't know how to await it while passing.
Is this even possible?
I need the function to be async because there is another async function I need to call from it. Another solution would be to be able to call and await the other async function (send_cars) from inside the sync function.
async def handle_cars(res):
print("GOT IT")
await send_cars()
async def get_cars():
req = grequests.get(URL, hooks=dict(response=handle_cars))
job = grequests.send(req, grequests.Pool(1))
How do I set the response argument to await the function? Or how do I await send_cars if I make handle_cars synchronous?
Thanks
According to the OP's comments, he wishes to create a request in the background, and call a callback when it finishes.
The way to do so can be implemented using asyncio.create_task() and using task.add_done_callback().
A simpler way however, will work by creating a new coroutine and running it in the background.
Demonstrated using aiohttp, it will work in the following way:
async def main_loop():
task = asyncio.create_task(handle_cars(URL))
while True:
...
async def handle_cars(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
await send_cars()
I'm writing a class that will do http requests using aiohttp. According to the docs I should not to create a ClientSession per request, so I want to reuse the same session.
code:
class TestApi:
def __init__(self):
self.session = aiohttp.ClientSession()
# async defs methods from here
When doing
TestApi()
I get the error: Unclosed client session.
What is the solution to persist the ClientSession object?
The expression TestApi() on a line by itself creates a TestApi object and immediately throws it away. aiohttp complaints that the session was never closed (either by leaving an async with block or with an explicit call to close()), but even without the warning it doesn't make sense not to assign the API object to a variable where it will be actually used.
To reuse the session, your code needs to have access to the session, or to an object that holds it:
async def fetch(url):
async with aiohttp.request('GET', url) as resp:
resp.raise_for_status()
return await resp.read()
async def main():
url1_data, url2_data = asyncio.gather(
fetch('http://url1'), fetch('http://url2'))
url3_data, url4_data = asyncio.gather(
fetch('http://url3'), fetch('http://url4'))
One option is to add a session parameter to fetch (and other functions) and consistently call it with a session created in main(). A better option is to create an API class and convert the global functions like fetch to methods:
class Http:
async def __aenter__(self):
self._session = aiohttp.ClientSession()
return self
async def __aexit__(self, *err):
await self._session.close()
self._session = None
async def fetch(self, url):
async with self._session.get(url) as resp:
resp.raise_for_status()
return await resp.read()
main() can still exist as a function, but it can consistently use the object that holds the session:
async def main():
async with Http() as http:
url1_data, url2_data = await asyncio.gather(
http.fetch('http://url1'), http.fetch('http://url2'))
url3_data, url4_data = await asyncio.gather(
http.fetch('http://url3'), http.fetch('http://url4'))
In the above code, the async with statement is used to ensure that the session is closed whenever the scope is left.