【问题标题】:How to get input from the console without blocking?如何在不阻塞的情况下从控制台获取输入?
【发布时间】:2020-01-01 10:36:28
【问题描述】:

我想做一个命令来向文本频道或用户发送消息,消息应该在控制台输入,但 input() 似乎“阻止”程序。虽然我已经尝试过线程来解决这个问题,但问题仍然没有解决。我该如何解决这个问题?

这样的简单代码:

import discord
import typing
from discord.ext import commands

class BasicCmd(commands.Cog):

    def __init__(self, client):
        self.client = client

    @commands.command()
    async def test(self, ctx, *, receiver: typing.Union[discord.User, discord.TextChannel]):
        '''
        I want to get input from console
        but input() block the program.
        '''
        content = input('Enter something: ')
        await receiver.send(content)

def setup(client):
    client.add_cog(BasicCmd(client))

如果我用线程来做:

import discord
import typing
import threading
from discord.ext import commands

class BasicCmd(commands.Cog):

    def __init__(self, client):
        self.client = client

    @commands.command()
    async def test(self, ctx, *, receiver: typing.Union[discord.User, discord.TextChannel]):
        '''
        I want to do this command with threading to figure out  
        this problem,but the problem still remain unsolve.
        '''
        content = threading.Thread(target=input,args=('Enter something: ',)).start()
        await receiver.send(content)
        '''It will  raise an HTTPException(Cannot send an enpty message,and the bot also "block" by "input")'''

def setup(client):
    client.add_cog(BasicCmd(client))

我已经修改了我的程序,但是输入仍然阻塞了我的程序。 代码(只是测试):

import discord
import typing
import queue
import threading
from discord.ext import commands

class BasicCmd(commands.Cog):

    def __init__(self, client):
        self.client = client

    @commands.command()
    async def test(self, ctx):
        inputQueue = queue.Queue()

        inputThread = threading.Thread(target=_read_kbd_input, args=(inputQueue,), daemon=True)
        # It still remain "blocking"
        inputThread.start()

        while (True):
            if (inputQueue.qsize() > 0):
                input_str = inputQueue.get()
                print("input_str = {}".format(input_str))
                return

def _read_kbd_input(inputQueue):
    print('Ready for keyboard input:')
    a=True
    while a:
        input_str = input()
        inputQueue.put(input_str)
        a=False
def setup(client):
    client.add_cog(BasicCmd(client))

【问题讨论】:

  • 我认为使用控制台执行此操作不是一个好主意,您需要为此创建一个 UI...但最终这可以帮助您:geeksforgeeks.org/simple-chat-room-using-python
  • Non-blocking, multi-threaded example 的答案重复; input 等待换行符或 EOF
  • @bufh 感谢您的帮助,但问题仍未解决。我已经编辑了我的帖子。
  • 考虑按键监听器而不是盲目地使用 input() 是不是很好?
  • @Kris 是个好主意,但是如果我想输入中文或其他语言,我应该如何处理按键监听器?

标签: python python-3.x blocking discord.py-rewrite console-input


【解决方案1】:

为输入创建一个新的异步定义

async def noinput():
  global inputoutput, askinput
  while True:
    if askinput==True
       inputoutput=input('input: ')
       askinput==False

那么,你必须在底部运行你的机器人之前运行它

client.loop.create_task(noinput())
client.run(token)

你的输入询问者应该是这样的

@client.event
async def on_message(message: discord.Message):
  global askinput, inputoutput
  if message.content.startswith("input"):
    askinput==True
    while askinput==True:
      await asyncio.sleep(1)
    output=inputoutput
    #do something with output

示例代码

async def noinput():
  global inputoutput, askinput
  while True:
    if askinput==True
       inputoutput=input('input: ')
       askinput==False

client=discord.Client()
async def on_message(message: discord.Message):
  global askinput, inputoutput
  if message.content.lower() == "input":
    askinput==True
    while askinput==True:
      await asyncio.sleep(1)
    message.channel.send(inputoutput)
client.loop.create_task(noinput())
client.run(token)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
相关资源
最近更新 更多