如何在线程内启动异步目标
Posted
技术标签:
【中文标题】如何在线程内启动异步目标【英文标题】:How to start async target inside thread 【发布时间】:2021-06-14 21:49:41 【问题描述】:我正在使用 pyCraft 库与 discord 和 minecraft 建立桥梁,我一直在尝试多种解决方案,例如 asyncio loop thing,但运行时它只运行 minecraft 客户端,并没有启动 discord 客户端直到我做一个键盘中断。我能弄清楚这如何工作的唯一方法是使用线程。此函数需要异步,因为它使用await ctx.send
方法发送到通道。我还需要不和谐并且该功能能够相互交互。异步:
import discord
import asyncio
from minecraft import authentication
from minecraft.exceptions import YggdrasilError
from minecraft.networking.connection import Connection
from minecraft.networking.packets import Packet, clientbound, serverbound
client = discord.Client()
async def mcClient(server='mc.hypixel.net', username='minecraft email', password='password', *, port=25565, version=340):
# version 340 - Minecraft 1.12.2
if password is None:
print("Connecting in offline mode...")
connection = Connection(
server, port, username=username)
else:
auth_token = authentication.AuthenticationToken()
try:
auth_token.authenticate(username, password)
except YggdrasilError as e:
print(e)
sys.exit()
print("(Online) Logged in as %s..." % auth_token.username)
connection = Connection(
server, port, auth_token=auth_token, initial_version=version)
# listener on join game
def handle_join_game(join_game_packet):
print('Connected.')
connection.register_packet_listener(
handle_join_game, clientbound.play.JoinGamePacket)
# print chat
def handle_chat(chat_packet):
cpke = chat_packet.json_data
print(f"Chat: cpke")
channel = client.get_channel(channel_id)
await channel.send(cpke)
connection.register_packet_listener(
handle_chat, clientbound.play.ChatMessagePacket)
connection.connect()
# listen for input and send message
while True:
try:
text = input()
packet = serverbound.play.ChatPacket()
packet.message = text
connection.write_packet(packet)
except KeyboardInterrupt:
print("Exiting client.")
sys.exit()
asyncio.get_event_loop().create_task(mcClient())
client.run(TOKEN)
线程(无异步):
import discord
import threading
from minecraft import authentication
from minecraft.exceptions import YggdrasilError
from minecraft.networking.connection import Connection
from minecraft.networking.packets import Packet, clientbound, serverbound
client = discord.Client()
def mcClient(server='mc.hypixel.net', username='minecraft email', password='password', *, port=25565, version=340):
# version 340 - Minecraft 1.12.2
if password is None:
print("Connecting in offline mode...")
connection = Connection(
server, port, username=username)
else:
auth_token = authentication.AuthenticationToken()
try:
auth_token.authenticate(username, password)
except YggdrasilError as e:
print(e)
sys.exit()
print("(Online) Logged in as %s..." % auth_token.username)
connection = Connection(
server, port, auth_token=auth_token, initial_version=version)
# listener on join game
def handle_join_game(join_game_packet):
print('Connected.')
connection.register_packet_listener(
handle_join_game, clientbound.play.JoinGamePacket)
# print chat
def handle_chat(chat_packet):
cpke = chat_packet.json_data
print(f"Chat: cpke")
connection.register_packet_listener(
handle_chat, clientbound.play.ChatMessagePacket)
connection.connect()
# listen for input and send message
while True:
try:
text = input()
packet = serverbound.play.ChatPacket()
packet.message = text
connection.write_packet(packet)
except KeyboardInterrupt:
print("Exiting client.")
sys.exit()
x = threading.Thread(target=mcClient(), daemon=True)
x.start()
client.run(TOKEN)
虽然这可行,但我无法发送消息或做任何与不和谐相关的事情。任何帮助将不胜感激!
编辑:我把整个函数和子函数放在一起,以便于理解
【问题讨论】:
尝试在你调用的函数后面添加await
。
我不能等待它,因为线程没有在异步函数中启动。我尝试将它放在异步函数中,但它返回“无法等待函数对象”
【参考方案1】:
asyncio.gather
可能会有所帮助。
import discord
import asyncio
import pyCraft
client = discord.Client()
async def mcClient():
# stuff
global connection
connection = pyCraft.connection(args)
connection.connect()
async def handle_chat():
# send message to discord here
# because of the global statement, you can reference connection from here too!
pass
asyncio.gather(mcClient(), handle_chat())
client.run(TOKEN)
【讨论】:
gather()
做了什么
@WindowsIsCool asyncio.gather
并行运行两个协程,以便 Discord 可以与 Minecraft 交互。
我对原始帖子进行了编辑,但我仍然不确定如何完全实现这一点,因为我需要定义一个侦听器。另外,我可以把函数变成一个类并调用它的子函数或类似的东西
你也不能用 () 来调用函数,否则它会在运行那一行时调用它以上是关于如何在线程内启动异步目标的主要内容,如果未能解决你的问题,请参考以下文章