如何用击键杀死while循环?

Chr*_*ris 71 python break while-loop

我正在读取串行数据并使用while循环写入csv文件.我希望用户能够在他们认为已经收集到足够的数据后杀死while循环.

while True:
    #do a bunch of serial stuff

    #if the user presses the 'esc' or 'return' key:
        break
Run Code Online (Sandbox Code Playgroud)

我使用opencv做了类似的事情,但它似乎没有在这个应用程序中工作(我真的不想为此函数导入opencv)...

        # Listen for ESC or ENTER key
        c = cv.WaitKey(7) % 0x100
        if c == 27 or c == 10:
            break
Run Code Online (Sandbox Code Playgroud)

所以.如何让用户摆脱循环?

另外,我不想使用键盘中断,因为脚本需要在while循环终止后继续运行.

Kei*_*ith 120

最简单的方法是用通常的Ctrl-C(SIGINT)中断它.

try:
    while True:
        do_something()
except KeyboardInterrupt:
    pass
Run Code Online (Sandbox Code Playgroud)

由于要引发Ctrl-C原因KeyboardInterrupt,只需将其捕获到循环外部并忽略它.

  • @克里斯:为什么不尝试一下。(然后评论) (2认同)
  • 我的“do_something()”从 USB 读取一些值,因此,如果在“do_something()”内部发出“^C”,则会出现严重的通信错误。相反,如果我在“while”中,在“do_something()”之外,一切都会顺利。所以,我想知道如何处理这种情况。我不确定我说得够清楚了。 (2认同)

小智 28

有一种解决方案不需要非标准模块,并且100%可移动

import thread

def input_thread(a_list):
    raw_input()
    a_list.append(True)

def do_stuff():
    a_list = []
    thread.start_new_thread(input_thread, (a_list,))
    while not a_list:
        stuff()
Run Code Online (Sandbox Code Playgroud)

  • 对于那些使用Python 3+的人来说只是一个注释:raw_input()已经重命名为input(),而线程模块现在是_thread. (3认同)
  • @Towhid只是`thread` - >`_thread`和`raw_input` - >`input`.您必须按Enter键才能输入该行.如果您想对任何密钥执行操作,请使用[getch](/sf/ask/35725021/). (2认同)

小智 13

pip install keyboard

import keyboard

while True:
    # do something
    if keyboard.is_pressed("q"):
        print("q pressed, ending loop")
        break
Run Code Online (Sandbox Code Playgroud)

  • 这个在 *nix 系统中不起作用,除非用户是 root(也称为从不) (4认同)
  • 新用户您好,感谢您的回答。您能否添加更多关于其工作原理的解释,以及如有必要的任何支持文档链接。仅粘贴代码并不总是有帮助,描述解决方案将帮助未来的读者了解您的答案是否适合他们。 (3认同)

ray*_*nnz 11

对于 Python 3.7,我复制并更改了 user297171 的非常好的答案,因此它适用于我测试的 Python 3.7 中的所有场景。

import threading as th

keep_going = True
def key_capture_thread():
    global keep_going
    input()
    keep_going = False

def do_stuff():
    th.Thread(target=key_capture_thread, args=(), name='key_capture_thread', daemon=True).start()
    while keep_going:
        print('still going...')

do_stuff()
Run Code Online (Sandbox Code Playgroud)


Lui*_*ose 10

以下代码适用于我.它需要openCV(import cv2).

该代码由一个无限循环组成,该循环不断寻找按下的键.在这种情况下,当按下'q'键时,程序结束.可以按下其他键(在此示例中为"b"或"k")以执行不同的操作,例如更改变量值或执行功能.

import cv2

while True:
    k = cv2.waitKey(1) & 0xFF
    # press 'q' to exit
    if k == ord('q'):
        break
    elif k == ord('b'):
        # change a variable / do something ...
    elif k == ord('k'):
        # change a variable / do something ...
Run Code Online (Sandbox Code Playgroud)

  • 好,但是cv2太重了,除非你已经把它用于别的东西了. (3认同)

小智 5

这是一个对我有用的解决方案。从这里和其他地方的帖子中得到了一些想法。在按下定义的键(abortKey)之前循环不会结束。循环尽可能快地停止并且不会尝试运行到下一次迭代。

from pynput import keyboard
from threading import Thread
from time import sleep

def on_press(key, abortKey='esc'):    
    try:
        k = key.char  # single-char keys
    except:
        k = key.name  # other keys    

    print('pressed %s' % (k))
    if k == abortKey:
        print('end loop ...')
        return False  # stop listener

def loop_fun():
    while True:
        print('sleeping')
        sleep(5)
        
if __name__ == '__main__':
    abortKey = 't'
    listener = keyboard.Listener(on_press=on_press, abortKey=abortKey)
    listener.start()  # start to listen on a separate thread

    # start thread with loop
    Thread(target=loop_fun, args=(), name='loop_fun', daemon=True).start()

    listener.join() # wait for abortKey
Run Code Online (Sandbox Code Playgroud)