如何在 jupyter notebook 中以交互方式 运行 discord.py?

How to run discord.py interactively in jupyter notebook?

在discord.py中,你可以初始化一个Client,然后用client.run()初始化运行。但是函数从来没有 returns.

如果我只想检索一些消息历史记录然后在 jupyter notebook 中使用它怎么办?

@bot.command()  
async def history(ctx):
    counter = 0
    messageList=[]
    async for message in ctx.channel.history(limit = 100):
        print(message.author, message.content)
        counter += 1
        messageList.append(message)

    await ctx.send(f'total **{counter}** messages in this channel.')

    # How to return the messageList to my jupyter notebook cell and I start playing with the messageList?

如何returnmessageList

没有好的方法来做到这一点。 discord.py 设计为启动一次 运行 直到您的程序终止,因为所有内部对象在机器人关闭时都被销毁,这使得机器人再次启动几乎不可能。并且不可能“暂停”discord.py 和 运行 你的代码然后恢复 discord.py,因为 Discord API 通过网络套接字进行通信,这依赖于源源不断的心跳和确认。

可能的解决方法是:

  • 在整个代码中使用单个事件循环。
  • 使用loop.run_until_complete()启动机器人的内部循环。
  • 每次需要 运行 机器人时创建一个新的 Client
  • 创建一个 on_ready 获取信息的事件句柄。
  • 缺点是您将无法与 Message 对象交互(即删除、编辑等),它们将只能查看。

示例:

import asyncio
import discord

TOKEN = "YOURBOTTOKEN"
loop = asyncio.get_event_loop()


def get_message_list(token, channel_id):
    client = discord.Client(loop=loop)
    message_list = []

    @client.event
    async def on_ready():
        nonlocal message_list
        channel = client.get_channel(channel_id)
        if not channel:  # incase the channel cache isn't fully populated yet
            channel = await client.fetch_channel(channel_id)

        async for message in channel.history(limit=100):
            message_list.append(message)
        await client.close()

    async def runner():
        try:
            await client.start(token)
        finally:
            if not client.is_closed():
                # Incase the bot was terminated abruptly (ie. KeyboardInterrupt)
                await client.close()

    loop.run_until_complete(runner())
    return message_list


message_list = get_message_list(TOKEN, channel_id=747699344911712345)
print("Message list for channel #1:", message_list)

# ... do stuff with message_list

message_list = get_message_list(TOKEN, channel_id=747699344911754321)
print("Message list for channel #2:", message_list)

# ... do more stuff with message_list

# Finally closes the event loop when everything's done
loop.close()

与其这样做,我建议您为您要完成的任务寻找另一种解决方案。