RuntimeError: asyncio.run() cannot be called from a running event loop. Anyone know what to do?

huangapple go评论75阅读模式
英文:

RuntimeError: asyncio.run() cannot be called from a running event loop. Anyone know what to do?

问题

以下是您要翻译的代码部分:

import tracemalloc
tracemalloc.start()
import asyncio
import discord
from discord.ext import commands
import characterai

character_ai_token = "character ai token here"
intents = discord.Intents.all()
client = characterai.pyCAI(character_ai_token)
bot = commands.Bot(command_prefix='!', intents=intents)

@bot.event
async def on_ready():
    print(f'Bot is ready. Logged in as {bot.user.name}')

target_channel_id = "channel_id_here"

@bot.event
async def on_message(message):
    data = await client.chat.send_message('CHAR', message, wait=True)
    if message.author == bot.user:
        return
    if message.channel.id != target_channel_id:
        return
    if message.content.startswith(bot.command_prefix):
        await bot.process_commands(message)
        return

    response = await data['replies'][0]['text']
    await message.channel.send(response)

async def start_bot():
    await bot.start("bot token")

async def main():
    await asyncio.create_task(start_bot())

asyncio.run(main())

希望这有所帮助。如果您需要进一步的信息或翻译,请告诉我。

英文:

Been working on a Discord bot that talks as a character.ai character, I utilized mainly an unofficial characterai API (https://github.com/kramcat/CharacterAI) and the discord.py library.
Code below:

import tracemalloc
tracemalloc.start()
import asyncio
import discord
from discord.ext import commands
import characterai

character_ai_token = "character ai token here"
intents = discord.Intents.all()
client = characterai.pyCAI(character_ai_token)
bot = commands.Bot(command_prefix='!', intents=intents)


@bot.event
async def on_ready():
    print(f'Bot is ready. Logged in as {bot.user.name}')


target_channel_id = "channel_id_here"


@bot.event
async def on_message(message):
    data = await client.chat.send_message('CHAR', message, wait=True)
    if message.author == bot.user:
        return
    if message.channel.id != target_channel_id:
        return
    if message.content.startswith(bot.command_prefix):
        await bot.process_commands(message)
        return

    response = await data['replies'][0]['text']
    await message.channel.send(response)


async def start_bot():
    await bot.start("bot token")

async def main():
    await asyncio.create_task(start_bot())

asyncio.run(main())

I tried using asyncio.create_task(), asyncio.get_event_loop(), loop.create_task(). I tried using asyncio.run() without putting the start_bot function into main()

Traceback (most recent call last):
  File "C:\Users\hp\Desktop\projects\discoBotchai\main.py", line 43, in <module>
    asyncio.run(main())
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\lib\asyncio\runners.py", line 33, in run
    raise RuntimeError(
RuntimeError: asyncio.run() cannot be called from a running event loop
sys:1: RuntimeWarning: coroutine 'main' was never awaited
Object allocated at (most recent call last):
  File "C:\Users\hp\Desktop\projects\discoBotchai\main.py", lineno 43

Process finished with exit code 1

答案1

得分: 1

I see you are trying to start your given Discord bot using await bot.start('...') in a start_bot function. Additionally, I see that you use the client variable in your on_message function to respond as the "character.ai character". I see a couple of issues unrelated to starting your Discord bot. Let us look at these, then look at how we can solve them.

General Issues

  • Starting your bot is currently redundant.
  • You should be using listeners for on_message instead of @bot.event. This is so you do not run into issues with processing commands and do not have to do it in your message listener.
  • Your target channel ID is a string, Discord.py uses integers for channel IDs.
  • When calling client.chat.send_message, you are passing the discord.Message object into the message parameter. This will cause issues, you need to be passing the message's clean content, if it has it.
  • You created an instance of pyCAI for your client, not an instance of pyAsyncCAI. pyCAI is not async, you need to be using the async client instance.
  • When retrieving the response from your client, you await the data. This will cause issues at runtime.

Getting the Bot Running

Let's take a look at your current block of code for starting your bot, then elaborate on how we can fix this to get you running.

async def start_bot():
    await bot.start("bot token")

async def main():
    await asyncio.create_task(start_bot())

asyncio.run(main())

In your current example, your main() function gets called, which spawns a task that runs the start_bot function. This function then calls await bot.start('bot token'). Your current implementation, unfortunately, neglects to start your async characterAI client as shown on the Github. To achieve this, we need to adjust your main function to launch both the bot and the client.

async def wrapped_start_bot():
    async with bot:
        await bot.start('bot token')

async def main():
    tasks = [
        asyncio.create_task(wrapped_start_bot()),
        asyncio.create_task(client.start(headless=True))
    ]
    await asyncio.wait(tasks)

In our adjusted version, we create two tasks: One that starts the bot, and another that starts our async character AI client. Afterward, we use asyncio.wait which will suspend the main coroutine until all tasks are done, or in our case, until the end of the bot's lifetime. Great, let's push all these changes together.

Finalized Revisions

import asyncio
import characterai

import discord
from discord.ext import commands

import tracemalloc
tracemalloc.start()

character_ai_token = "character ai token here"
intents = discord.Intents.all()
client = characterai.pyAsyncCAI(character_ai_token)
bot = commands.Bot(command_prefix='!', intents=intents)

@bot.event
async def on_ready():
    print(f'Bot is ready. Logged in as {bot.user.name}')

# Set target channel ID to be an integer here:
target_channel_id: int = 000000001

# Utilizing bot.listen() instead of @bot.event as to 
# not worry about manually processing commands.
@bot.listen('on_message')
async def on_message(message: discord.Message):
    if not message.content:
        # This message has no content!
        return

    if message.author.bot:
        # This message has been sent by a bot!
        return

    if message.channel.id != target_channel_id:
        # This is not in the correct channel!
        return 

    # But how do we know this isn't a command? Let's ensure this isn't a valid command!
    context = await bot.get_context(message)
    if context.valid:
        # This is a valid command, which means our bot should not respond to it!
        return 

    # We know all the following items:
    # - This message has content.
    # - This message was not sent by a bot.
    # - This message is in the correct channel.
    # - This message is not a bot command.

    data = await client.chat.send_message('CHAR', message.clean_content, wait=True)
    response = data['replies'][0]['text']
    await message.reply(response, mention_author=False)

async def wrapped_start_bot():
    async with bot:
        await bot.start('bot token')

async def main():
    tasks = [
        asyncio.create_task(wrapped_start_bot()),
        asyncio.create_task(client.start(headless=True))
    ]
    await asyncio.wait(tasks)

Great. We've corrected launching the bot and client as well as fixed some other general issues with your current implementation!

英文:

I see you are trying to start your given Discord bot using await bot.start('...') in a start_bot function. Additionally, I see that you use the client variable in your on_message function to respond as the "character.ai character". I see a couple of issues unrelated to starting your Discord bot. Let us look at these, then look at how we can solve them.

General Issues

  • Starting your bot is currently redundant.
  • You should be using listeners for on_message instead of @bot.event. This is so you do not run into issues with processing commands and do not have to do it in your message listener.
  • Your target channel ID is a string, Discord.py uses integers for channel IDs.
  • When calling client.chat.send_message, you are passing the discord.Message object into the message parameter. This will cause issues, you need to be passing the message's clean content, if it has it.
  • You created an instance of pyCAI for your client, not an instance of pyAsyncCAI. pyCAI is not async, you need to be using the async client instance.
  • When retrieving the response from your client, you await the data. This will cause issues at runtime.

Getting the Bot Running

Let's take a look at your current block of code for starting your bot, then elaborate on how we can fix this to get you running.

async def start_bot():
    await bot.start("bot token")

async def main():
    await asyncio.create_task(start_bot())

asyncio.run(main())

In your current example, your main() function gets called, which spawns a task that runs the start_bot function. This function then calls await bot.start('bot token'). Your current implementation, unfortunately, neglects to start your async characterAI client as shown on the Github. To achieve this, we need to adjust your main function to launch both the bot and the client.

async def wrapped_start_bot():
    async with bot:
        await bot.start('bot token')

async def main():
    tasks = [
        asyncio.create_task(wrapped_start_bot()),
        asyncio.create_task(client.start(headless=True)
    ]
    await asyncio.wait(tasks)

In our adjusted version, we create two tasks: One that starts the bot, and another that starts our async character AI client. Afterward, we use asyncio.wait which will suspend the main coroutine until all tasks are done, or in our case, until the end of the bot's lifetime. Great, let's push all these changes together.

Finalized Revisions

import asyncio
import characterai

import discord
from discord.ext import commands

import tracemalloc
tracemalloc.start()

character_ai_token = "character ai token here"
intents = discord.Intents.all()
client = characterai.pyAsyncCAI(character_ai_token)
bot = commands.Bot(command_prefix='!', intents=intents)


@bot.event
async def on_ready():
    print(f'Bot is ready. Logged in as {bot.user.name}')


# Set target channel ID to be an integer here:
target_channel_id: int = 000000001


# Utilizing bot.listen() instead of @bot.event as to 
# not worry about manually processing commands.
@bot.listen('on_message')
async def on_message(message: discord.Message):
    if not message.content:
        # This message has no content!
        return

    if message.author.bot:
        # This message has been sent by a bot!
        return

    if message.channel.id != target_channel_id:
        # This is not in the correct channel!
        return 

    # But how do we know this isn't a command? Let's ensure this isn't a valid command!
    context = await bot.get_context(message)
    if context.valid:
        # This is a valid command, which means our bot should not respond to it!
        return 

    # We know all the following items:
    # - This message has content.
    # - This message was not sent by a bot.
    # - This message is in the correct channel.
    # - This message is not a bot command.


    data = await client.chat.send_message('CHAR', message.clean_content, wait=True)
    response = data['replies'][0]['text']
    await message.reply(response, mention_author=False)

async def wrapped_start_bot():
    async with bot:
        await bot.start('bot token')

async def main():
    tasks = [
        asyncio.create_task(wrapped_start_bot()),
        asyncio.create_task(client.start(headless=True)
    ]
    await asyncio.wait(tasks)

Great. We've corrected launching the bot and client as well as fixed some other general issues with your current implementation!

huangapple
  • 本文由 发表于 2023年5月28日 22:10:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76351907.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定