经常问的问题

这是有关使用 qq.py 及其扩展模块的常见问题列表。随意提出一个新问题或通过Pull Request提交一个。

Coroutines

关于协程和 asyncio 的问题属于这里。

什么是协程?

coroutine 是一个必须使用 awaityield from 调用的函数。 当 Python 遇到 await 时,它会在那个点停止函数的执行并处理其他事情,直到它回到那个点并完成它的工作。 这允许你的程序同时执行多项操作,而无需使用线程或复杂的多处理。

如果你忘记 await 协程,则协程将不会运行。永远不要忘记 await 协程。

我在哪里可以使用 await

你只能在 async def 函数中使用 await,而不能在其他任何地方使用。

“阻塞”是什么意思?

在异步编程中,阻塞调用本质上是函数中所有不是 await 的部分。但是不要绝望,因为并非所有形式的阻塞都是不好的! 使用阻塞调用是不可避免的,但你必须努力确保不会过度阻塞函数。 请记住,如果你阻塞的时间过长,那么你的机器人将冻结,因为它此时尚未停止函数的执行以执行其他操作。

如果启用日志记录,此库将尝试警告你正在发生阻塞并显示消息: 心跳被阻塞超过 N 秒。 有关启用日志记录的详细信息,请参阅 设置日志

阻塞时间过长的常见原因是 time.sleep()。不要那样做。使用 asyncio.sleep() 代替。类似于这个例子:

# 坏坏
time.sleep(10)

# 很好
await asyncio.sleep(10)

阻塞时间过长的另一个常见原因是使用带有著名模块 Requests: HTTP for Humans™ 的 HTTP 请求。 虽然 Requests: HTTP for Humans™ 是非异步编程的一个了不起的模块,但它不是 asyncio 的好选择,因为某些请求可能会阻塞事件循环太久。 相反,请使用 aiohttp 库。

考虑以下示例:

# 坏坏
r = requests.get('http://aws.random.cat/meow')
if r.status_code == 200:
    js = r.json()
    await channel.send(js['file'])

# 很好
async with aiohttp.ClientSession() as session:
    async with session.get('http://aws.random.cat/meow') as r:
        if r.status == 200:
            js = await r.json()
            await channel.send(js['file'])

通用

关于库使用的一般问题属于这里。

在哪里可以找到使用示例?

示例代码可以在 示例文件夹 找到。

如何向特定频道发送消息?

你必须直接获取通道,然后调用适当的方法。 例子:

channel = client.get_channel(12324234183172)
await channel.send('hello')

我如何私聊?

获取 User 或 Member 对象并调用 abc.Messageable.send() 。 例如::

user = message.author
await user.send('Hi', reference = message)

我如何发送本地图片?

获取 qq.File 并调用 abc.Messageable.send() 。 例如::

file = qq.File("./img.png")
await channel.send(file=file)

如何获取已发送消息的 ID?

abc.Messageable.send() 返回发送的:class:Message。 消息的 ID 可以通过 Message.id 访问:

message = await channel.send('嗯...')
message_id = message.id

如何向消息添加表情?

你需要使用 Message.add_reaction() 方法。

如果要使用 unicode 表情符号,则必须在字符串中传递有效的 unicode 代码点。 在你的代码中,你可以用几种不同的方式编写它: - '👍' - '\U0001F44D' - '\N{THUMBS UP SIGN}'

示例::

emoji = '\N{THUMBS UP SIGN}'
# or '\U0001f44d' or '👍'
await message.add_reaction(emoji)

对于自定义表情符号,你应该传递一个 PartialEmoji 实例。 你也可以传递一个``’emoji:id’`` 字符串,但是如果你 可以使用上述表情符号,你应该可以使用:meth:PartialEmoji.from_str 通过ID获取表情符号。 表情符号 ID 可以通过消息获取,或者在官方文档获取。

示例::

await message.add_reaction('emoji:10')

我如何在后台运行一些东西?

检查 background_task.py 示例。

我如何获得特定对象?

有多种方法可以做到这一点。 如果你有特定对象的 ID,则可以使用以下功能之一:

以下使用 HTTP 请求:

如果上述函数对你没有帮助,那么使用 utils.find()utils.get() 将有助于查找特定对象。

快速示例:

# 按名称查找频道
guild = qq.utils.get(client.guilds, name='My Server')

# 确保检查它是否被找到
if guild is not None:
    # 按名称查找子频道
    channel = qq.utils.get(guild.text_channels, name='cool-channel')

如何发出网络请求?

要发出请求,你应该使用非阻塞库。 这个库已经使用并需要一个 第三方库来发出请求,aiohttp

快速示例:

async with aiohttp.ClientSession() as session:
    async with session.get('http://aws.random.cat/meow') as r:
        if r.status == 200:
            js = await r.json()

有关更多信息,请参阅 aiohttp 的完整文档

命令扩展

qq.ext.commands 有关的问题。

为什么定义 on_message 之后我的命令用不了了?

覆盖默认提供的 on_message 禁止运行任何额外的命令。 要解决此问题,请在 on_message 末尾添加 bot.process_commands(message) 行。 例如:

@bot.event
async def on_message(message):
    # 在这里做一些额外的事情

    await bot.process_commands(message)

或者,你可以将 on_message 逻辑放入 listener。 在此设置中,你不应该手动调用 bot.process_commands() 。 这也允许你异步地做多项响应到一条消息。 例子:

@bot.listen('on_message')
async def whatever_you_want_to_call_it(message):
    # 在这里做事
    # 这里不处理命令

为什么我的参数需要引号?

在一个简单的命令中定义为:

@bot.command()
async def echo(ctx, message: str):
    await ctx.send(message)

通过 ?echo a b c 调用它只会获取第一个参数而忽略其余参数。 要解决此问题,你需要在边上加上引号 ?echo "a b c" 或添加多个你需要的参数。 例子:

@bot.command()
async def echo(ctx, a, b, c, message: str):
    await ctx.send(message)

这将允许你使用 ?echo a b c 而不需要引号。

我如何获得原始的 Message

Context 包含该属性,使用 message 获取原始信息。

例子:

@bot.command()
async def length(ctx):
    await ctx.send(f'你的留言是 {len(ctx.message.content)} 字符长度。')

如何创建子命令?

使用 group() 装饰器。 这会将回调转换为 Group ,它允许你将命令添加到作为“子命令”运行的组。 这些组也可以任意嵌套。

例子:

@bot.group()
async def git(ctx):
    if ctx.invoked_subcommand is None:
        await ctx.send('传递了无效的 git 命令...')

@git.command()
async def push(ctx, remote: str, branch: str):
    await ctx.send(f'Pushing to {remote} {branch}')

这可以用作 ?git push origin master