Python 如何通过击键杀死while循环?
我正在使用while循环读取串行数据并写入csv文件。我希望用户一旦觉得收集了足够的数据,就能够终止while循环Python 如何通过击键杀死while循环?,python,while-loop,break,Python,While Loop,Break,我正在使用while循环读取串行数据并写入csv文件。我希望用户一旦觉得收集了足够的数据,就能够终止while循环 while True: #do a bunch of serial stuff #if the user presses the 'esc' or 'return' key: break 我使用opencv做过类似的事情,但它在这个应用程序中似乎不起作用(而且我真的不想只为这个函数导入opencv) 所以。如何让用户跳出循环 另外,我不想使用键盘
while True:
#do a bunch of serial stuff
#if the user presses the 'esc' or 'return' key:
break
我使用opencv做过类似的事情,但它在这个应用程序中似乎不起作用(而且我真的不想只为这个函数导入opencv)
所以。如何让用户跳出循环
另外,我不想使用键盘中断,因为在while循环终止后,脚本需要继续运行。最简单的方法就是用通常的
Ctrl-C
(SIGINT)中断它
由于Ctrl-C
会引发键盘中断
,只需在循环外捕捉它并忽略它。pyHook可能会有所帮助
参见键盘挂钩;如果您想要特定的键盘交互,而不仅仅是使用键盘中断,这是更普遍的
另外,一般来说(取决于您的使用),我认为仍然可以使用Ctrl-C选项来终止您的脚本是有意义的
另请参见上一个问题:有一种解决方案不需要非标准模块,并且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()
下面的代码适合我。它需要openCV(导入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 ...
始终存在
sys.exit()
Python核心库中的系统库有一个退出函数,在原型制作时非常方便。
该准则大致如下:
import sys
while True:
selection = raw_input("U: Create User\nQ: Quit")
if selection is "Q" or selection is "q":
print("Quitting")
sys.exit()
if selection is "U" or selection is "u":
print("User")
#do_something()
对于Python3.7,我复制并更改了user297171提供的非常好的答案,因此它可以在我测试的Python3.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()
这可能会有帮助
使用安装pynput--
pip安装pynput
from pynput.keyboard import Key, Listener
def on_release(key):
if key == Key.esc:
# Stop listener
return False
# Collect events until released
while True:
with Listener(
on_release=on_release) as listener:
listener.join()
break
对于enter,使用“enter”我修改了rayzinz的答案,以一个特定的键结束脚本,在本例中是escape键
import threading as th
import time
import keyboard
keep_going = True
def key_capture_thread():
global keep_going
a = keyboard.read_key()
if a== "esc":
keep_going = False
def do_stuff():
th.Thread(target=key_capture_thread, args=(), name='key_capture_thread', daemon=True).start()
i=0
while keep_going:
print('still going...')
time.sleep(1)
i=i+1
print (i)
print ("Schleife beendet")
do_stuff()
这是我用线程和标准库找到的解决方案
循环一直持续,直到按下一个键
返回作为单个字符串按下的键
适用于Python 2.7和3
import thread
import sys
def getch():
import termios
import sys, tty
def _getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
return _getch()
def input_thread(char):
char.append(getch())
def do_stuff():
char = []
thread.start_new_thread(input_thread, (char,))
i = 0
while not char :
i += 1
print "i = " + str(i) + " char : " + str(char[0])
do_stuff()
从兔子洞下面的这个线程,我来到了这个,在Win10和Ubuntu20.04上工作。我想要的不仅仅是杀死脚本,还要使用特定的密钥,而且它必须在MS和Linux中都能工作
import _thread
import time
import sys
import os
class _Getch:
"""Gets a single character from standard input. Does not echo to the screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()
def __call__(self): return self.impl()
class _GetchUnix:
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
msvcrt_char = msvcrt.getch()
return msvcrt_char.decode("utf-8")
def input_thread(key_press_list):
char = 'x'
while char != 'q': #dont keep doing this after trying to quit, or 'stty sane' wont work
time.sleep(0.05)
getch = _Getch()
char = getch.impl()
pprint("getch: "+ str(char))
key_press_list.append(char)
def quitScript():
pprint("QUITTING...")
time.sleep(0.2) #wait for the thread to die
os.system('stty sane')
sys.exit()
def pprint(string_to_print): #terminal is in raw mode so we need to append \r\n
print(string_to_print, end="\r\n")
def main():
key_press_list = []
_thread.start_new_thread(input_thread, (key_press_list,))
while True:
#do your things here
pprint("tick")
time.sleep(0.5)
if key_press_list == ['q']:
key_press_list.clear()
quitScript()
elif key_press_list == ['j']:
key_press_list.clear()
pprint("knock knock..")
elif key_press_list:
key_press_list.clear()
main()
下面是一个简单的Windows解决方案,它安全地结束当前迭代,然后退出。我用了一个反例,用“Esc”键打破循环并退出。它使用包中的函数。仅出于地役权原因调用时间包(设置事件之间的时间延迟) kbhit()如果按键等待读取,则函数返回True getch()函数读取按键并将结果字符作为字节字符串返回。它可以与任何钥匙一起使用
b'\x1b'是“Esc”键的字节字符串字符。这里有一个对我有效的解决方案。从这里和其他地方的帖子中得到一些想法。在按下定义键(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
@克丽丝:你为什么不试试呢。(然后评论)此崩溃(我得到错误跟踪)是
^C
是在do\u something()
中发出的。如何避免这种情况?我的do_something()
从USB读取一些值,因此,如果在我在do_something()
内时发出^C
,我会收到严重的通信错误。相反,如果我在中,而中,在do_something()
之外,一切都很顺利。所以,我想知道如何处理这种情况。我不确定我说得是否足够清楚。@Atcold,所以您有一个正在使用的编译扩展模块。它是什么样的模块?这是一个正在包装的通用C库吗?我可以调用pyVISA
和matplotlib
,这样我就可以实时可视化我的测量结果。我有时会犯一些古怪的错误。我想我应该打开一个单独的问题,不要再污染你的答案了……请注意使用Python 3+的人:raw_input()已重命名为input(),线程模块现在是_thread。根据Python 3文档,在Python 3中不起作用:线程与中断进行奇怪的交互:键盘中断异常将由任意线程接收。(当信号模块可用时,中断总是转到主线程。)“@Towhid,但这不使用中断。它使用从stdin读取。@Artyer如果我没有弄错的话,所有的击键都会引发中断,因为它们是由硬件引发的。此代码对您有效吗?如果有效,您是否进行了任何特定更改?@Towhid只是线程
->\u线程
和原始输入
->输入
。您必须按enter键才能输入该行。如果你想在任何一把钥匙上使用。很好,但是cv2太重了,除非你已经在用它做其他的事情。为什么255@Talespin_Kit&0xff“屏蔽变量,使其仅保留最后8位中的值,并忽略所有其余位。基本上,它可以确保结果在0-255之间。注意,我从来没有在opencv中这样做过,一切都很好。我不知道我是否做错了什么,但我不知道如何停止这个循环?你是怎么做到的?@Mihkel你必须按这个键。这将导致循环退出。这很不错,但不能推广到除enter键以外的其他键。在python2.7上对我不起作用,但在Python3上起作用。在我的脑海中,多线程也是如此,但我非常喜欢上面@Keith的答案。简单明了,你好!虽然这段代码可以解决这个问题,但如何以及为什么解决这个问题将真正有助于提高
import thread
import sys
def getch():
import termios
import sys, tty
def _getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
return _getch()
def input_thread(char):
char.append(getch())
def do_stuff():
char = []
thread.start_new_thread(input_thread, (char,))
i = 0
while not char :
i += 1
print "i = " + str(i) + " char : " + str(char[0])
do_stuff()
import _thread
import time
import sys
import os
class _Getch:
"""Gets a single character from standard input. Does not echo to the screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()
def __call__(self): return self.impl()
class _GetchUnix:
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
msvcrt_char = msvcrt.getch()
return msvcrt_char.decode("utf-8")
def input_thread(key_press_list):
char = 'x'
while char != 'q': #dont keep doing this after trying to quit, or 'stty sane' wont work
time.sleep(0.05)
getch = _Getch()
char = getch.impl()
pprint("getch: "+ str(char))
key_press_list.append(char)
def quitScript():
pprint("QUITTING...")
time.sleep(0.2) #wait for the thread to die
os.system('stty sane')
sys.exit()
def pprint(string_to_print): #terminal is in raw mode so we need to append \r\n
print(string_to_print, end="\r\n")
def main():
key_press_list = []
_thread.start_new_thread(input_thread, (key_press_list,))
while True:
#do your things here
pprint("tick")
time.sleep(0.5)
if key_press_list == ['q']:
key_press_list.clear()
quitScript()
elif key_press_list == ['j']:
key_press_list.clear()
pprint("knock knock..")
elif key_press_list:
key_press_list.clear()
main()
pip install keyboard
import keyboard
while True:
# do something
if keyboard.is_pressed("q"):
print("q pressed, ending loop")
break
import msvcrt, time
print("Press 'Esc' to stop the loop...")
x = 0
while True:
x += 1
time.sleep(0.5)
print(x)
if msvcrt.kbhit():
if msvcrt.getch() == b'\x1b':
print("You have pressed Esc! See you!")
time.sleep(2)
break
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