python - 需要在同步函数中等待一个函数
问题描述
我已经尝试解决这个问题 2 天了,在 StackOverflow 中阅读了 50 个问题以及很多关于 Python 的文档。我不知道还能尝试什么。
我的代码
import discord
import re
from datetime import datetime
import mysql.connector
from discord.ext import commands, tasks
from discord.utils import get
import atexit
from pynput import keyboard
import asyncio
from asgiref.sync import async_to_sync, sync_to_async
# The currently active modifiers
current = set()
# The key combination to check
COMBINATIONS_MUTE = [
{keyboard.Key.shift, keyboard.KeyCode(char='a')},
{keyboard.Key.shift, keyboard.KeyCode(char='A')}
]
COMBINATIONS_UNMUTE = [
{keyboard.Key.shift, keyboard.KeyCode(char='b')},
{keyboard.Key.shift, keyboard.KeyCode(char='B')}
]
GUILD_ID=guild_id
CHANNELS = ""
GUILD = ""
VOICE_CHANNEL = ""
client = commands.Bot(command_prefix = ".")
def get_channel(name):
global CHANNELS
for channel in CHANNELS:
if (channel.name == name) and (channel.type.name == "voice"):
return channel
return False
def get_voice_channels():
global CHANNELS
channels = []
for channel in CHANNELS:
if (channel.type.name == "voice"):
channels.append(channel)
return channels
async def mute_all():
global VOICE_CHANNELS
print("mute all")
for channel in VOICE_CHANNELS:
for member in channel.members:
await member.edit(mute=True)
async def unmute_all():
global VOICE_CHANNELS
print("unmute all")
for channel in VOICE_CHANNELS:
for member in channel.members:
await member.edit(mute=False)
def on_press(key):
if any([key in COMBO for COMBO in COMBINATIONS_MUTE]) and not key in current:
current.add(key)
if any(all(k in current for k in COMBO) for COMBO in COMBINATIONS_MUTE):
asyncio.run(mute_all())
elif any([key in COMBO for COMBO in COMBINATIONS_UNMUTE]):
current.add(key)
if any(all(k in current for k in COMBO) for COMBO in COMBINATIONS_UNMUTE):
asyncio.run(unmute_all())
def on_release(key):
if any([key in COMBO for COMBO in COMBINATIONS_MUTE]):
current.remove(key)
elif any([key in COMBO for COMBO in COMBINATIONS_UNMUTE]):
current.remove(key)
@client.event
async def on_ready():
global GUILD
global CHANNELS
global VOICE_CHANNELS
global GUILD_ID
GUILD = client.get_guild(GUILD_ID)
CHANNELS = GUILD.channels
VOICE_CHANNELS = get_voice_channels()
print("bot ready")
loop = asyncio.get_event_loop()
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
client.run('token')
基本上它应该做的是:
- 当我按 Shift+A 时,每个语音通道中的所有人都会静音。
- 当我按下 Shitf+B 时,每个语音通道中的所有人都会取消静音。
问题是我需要等待,member.edit()
但我不能,因为我不能等待mute_all()
,也不是unmute_all()
因为on_press(key)
不是异步的,我不能让它异步,因为keyboard_listener 不会让我。
我试过的(没有奏效)
- 使用.
asyncio.run()
_member.edit()
- 使用.
asyncio.run()
_mute_all()
- 使
on_press(key)
异步。 - 使用.
async_to_sync()
_member.edit()
- 使用.
async_to_sync()
_mute_all()
我不知道还能尝试什么。
解决方案
keyboard.Listener 不是异步的,所以它会阻塞事件循环on_ready
,你需要在执行器中初始化监听器,在这种情况下我们可以使用默认的。
这是我为使该位正常工作而进行的所有更改:
def keyboard_listener():
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
@client.event
async def on_ready():
global GUILD
global CHANNELS
global VOICE_CHANNELS
global GUILD_ID
GUILD = client.get_guild(GUILD_ID)
CHANNELS = GUILD.channels
VOICE_CHANNELS = get_voice_channels()
print("bot ready")
loop.run_in_executor(None, keyboard_listener)
loop = asyncio.get_event_loop()
然后我asyncio.run
用loop.create_task
如果我的指示不清楚,我有一个功能版本,请随时提问。
从 async 到 sync 再到 async 是很恶心的,但是嘿它有效,所以我猜它并不愚蠢
我还稍微更改了您的mute_all
和unmute_all
,因为您当前的实施只会影响机器人最初连接时频道中的语音用户。这是我的更改示例:
async def mute_all():
print("mute all")
for channel in client.get_guild(GUILD_ID).channels:
if not channel.type.name == "voice":
continue
for member in channel.members:
await member.edit(mute=True)
推荐阅读
- javascript - Node.js MSSQL包查询功能不返回数据
- sql-server - dacpac 文件向 LocalDB 发布错误:“无法部署该元素。该元素包含无法在目标数据库中重新创建的状态。”
- python - Finding the frequency that each column is a row minimum
- python - 删除熊猫列中的特定单词
- node.js - 为什么我在我的 mongoose 预架构上遇到这些错误?
- javascript - 在烧瓶中提交之前验证 DOM 中的 html 输入
- for-loop - Python - for 循环 - 理解
- java - 反序列化对象运行问题
- json - Dialogflow Fulfillment - 在 Google Spreedsheet 中创建新行(使用 Sheetdb io) - 这是代码
- c# - 验证 txt 文件中是否存在字符串并更新以前使用的 txt 文件