当程序在 python 中为 运行 时,如何防止用户输入控制台?

How to prevent user input into console when program is running in python?

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

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

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

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

C:\Users\User>awdsaawdsadwsaasdwaws

基本上,在代码 运行ning 时按下任何键。当命令提示符中的其他内容 运行 时也会发生这种情况,但我想知道如何在 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)

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

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

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

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

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

,这将是非常困难的。

问题是在您尝试从中读取之前,无法知道标准输入流上是否有输入。但是,如果您尝试从中读取,您的脚本将暂停,直到收到 'end of line' 或 'end of file'。如果用户只是敲击按键,那将不会发生,所以你会一直阅读直到他们按下 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')