程序在python中运行时如何防止用户输入控制台? [复制]

Posted

技术标签:

【中文标题】程序在python中运行时如何防止用户输入控制台? [复制]【英文标题】:How to prevent user input into console when program is running in python? [duplicate] 【发布时间】:2021-04-13 22:18:08 【问题描述】:

我正在用 python 制作一个在控制台上运行的游戏。当我退出游戏时,我按下的所有键都会自动输入。我该如何阻止这种情况发生?另外,当我使用input() 函数时,我仍然希望有用户输入。顺便说一下,这是在 Windows 上。

如果你想要代码,这有同样的“问题”:

for _ in range(100000):
    print("Hello")

当程序在命令提示符下完成时,会出现:

C:\Users\User>awdsaawdsadwsaasdwaws

基本上,代码运行时按下的任何键。当其他东西也在命令提示符下运行时会发生这种情况,但我想知道如何在 python 中禁用它。

编辑:我一直在挖掘,发现我正在寻找的是刷新或清除键盘缓冲区。我将我的问题标记为与另一个有几个答案的问题重复,但这个问题最适合我:

def flush_input():
    try:
        import msvcrt
        while msvcrt.kbhit():
            msvcrt.getch()
    except ImportError:
        import sys, termios    #for linux/unix
        termios.tcflush(sys.stdin, termios.TCIOFLUSH)

【问题讨论】:

如果你能提供一些代码就太好了,这样我们就不用猜测了 这似乎不太可能,除非您的程序注册按下的键,然后循环每个按下的键并使用 python 模拟它。但是你会知道为什么会这样。 好吧,从我的推论(因为你还没有提供代码)我会说有打印语句可以打印用户在最后使用input() 输入的所有内容 @Matiiss 控制台中的游戏是蛇游戏。当程序运行时,我希望用户可以使用input() 更改设置。这就是为什么有输入。但除此之外,当你死的时候,你按下的所有键都在下一行,比如C:\Users\User>awdsadwdasdawdasdasdsawdas 正如我所说,您应该提供代码。如果我不知道您在代码中添加了什么,您认为我将如何回答为什么会发生这种情况? 【参考方案1】:

发生这种情况是因为您的计算机注册了击键,并且在控制台上,这些击键在 stdin 输入流中可用。

如果您将脚本保存为test.py 并运行python test.py 并开始输入一些击键,例如abc,这些字母将在标准输入中。

您的脚本不会读取它们,因为它不会触及该流,因为您没有使用 input() 或任何其他会读取该流的调用。所以你的脚本完成了,字符仍然在标准输入中,提示返回并且 it 读取这些字符,并给出给定的结果:

Hello
Hello
Hello
PS C:\Users\username> abc

为避免这种情况,您可以在脚本末尾读取/刷新输入缓冲区。但是,如果您需要它在所有操作系统和不同的脚本运行模式下工作(直接从 cmd、IDLE、在其他 IDE 中等),这将是非常困难的。

问题是,在您尝试从中读取之前,无法知道标准输入流上是否有输入。但是,如果您尝试从中读取,您的脚本将暂停,直到收到“行尾”或“文件尾”。如果用户只是敲击键,那将不会发生,所以你最终会一直阅读,直到他们敲击 Ctrl+Break 或 Ctrl+C 之类的东西。

这是一种我认为相对稳健的方法,但我建议您在您认为可能使用脚本的场景和环境中对其进行测试:

import sys
import threading
import queue
import os
import signal

for _ in range(100000):
    print("Hello")

timeout = 0.1  # sec


def no_input():
    # stop main thread (which is probably blocked reading input) via an interrupt signal
    # only available for windows in Python version 3.2 or higher
    os.kill(os.getpid(), signal.SIGINT)
    exit()


# if a sigint is received, exit the main thread (you could call another function to do work first and then exit()
signal.signal(signal.SIGINT, exit)

# input is stored here, until it's dealt with
input_queue = queue.Queue()


# read all available input until main thread exit
def get_input():
    while True:
        try:
            # read input, not doing anything with it
            _ = input_queue.get(timeout=timeout)
        except queue.Empty:
            no_input()


reading_thread = threading.Thread(target=get_input)
reading_thread.start()

# main loop: put any available input in the queue, will wait for input if there is none
for line in sys.stdin:
    input_queue.put(line)

# wait for reading thread
reading_thread.join()

它基本上从第二个线程读取输入,允许主线程获取输入并可能对它做一些事情,直到什么都没有,然后它只是告诉主线程退出。请注意,这将导致您的脚本以退出代码 2 退出,这可能不是您想要的。

另请注意,您仍会在屏幕上看到输入,但不会再将其传递到终端:

Hello
Hello
Hello
abc
PS C:\Users\username>

我不知道是否有一种简单的方法可以避免回声,除了在 Linux 上执行stty -echo 之类的操作。您当然可以在脚本结束时调用系统来清除屏幕:

from subprocess import call
from os import name as os_name

call('clear' if os_name =='posix' else 'cls')

【讨论】:

以上是关于程序在python中运行时如何防止用户输入控制台? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在调试器中运行时中断下一个输出

如何使用 python 为 Web 元素生成 Xpath(在我的脚本中运行时)?

找出python程序中运行时最耗时间的部分

自动布局 - 在模拟器中运行时文本字段垂直拉伸

程序在tkinter中运行时如何制作新标签?

在 VS Code 中运行时 Python 跳过函数