在串口接收数据时中断for循环
我想知道怎么让我的程序在从串口接收到“K”这个字符时,能够中断正在运行的for循环。
代码如下:
import serial
from time import sleep
ser = serial.Serial(port='/dev/ttyUSB0',baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=0)
while 1:
for line in ser.read(1):
input+=chr(line)
if input == 'S':
for x in range (1 , 10): # this is the loop i want to break
print(x)
sleep(1)
if input == 'K':
print('K received -> BREAK')
break
print("Finished")
这样的话,程序会在for循环结束后打印出'K received -> BREAK'。
1 个回答
0
你不能这样做,因为程序还没有在运行。
你的程序在执行完for x in range (1, 10)
这个循环之前,不会再从输入中读取其他字符。
想象一下输入是'SK'
。你的程序会先读取'S'
这个字符,然后执行循环。在每次循环中,sleep
会让整个线程暂停,而不仅仅是暂停这个循环。所以你的程序会停下9次,每次至少停一秒,才会处理下一个字符'K'
,这时它会跳出for line in ser.read(1)
这个循环(另外要注意,这个循环只会执行一次,因为ser.read(1)
只读取一个字节)。
如果我理解得没错,你是想在从串口输入接收到某个字符后,运行一个可能比较长的任务,并且如果接收到另一个字符,就停止这个正在运行的任务。
为了做到这一点,你应该把任务放在一个单独的线程中运行。
你可能想把任务封装在一个管理线程的类里,但我能想到的最简单的方法是为你的任务写一个函数,然后在一个线程中执行它。你可以使用threading.Event
来告诉任务在主线程接收到停止字符时停止。
import serial
import threading
from time import sleep
ser = serial.Serial(port='/dev/ttyUSB0',baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=0)
thread = None
stop_task = threading.Event()
def do_task():
for i in xrange(10):
if stop_task.is_set():
break
print(i)
sleep(1)
while True:
byte = ser.read(1): # No need for a loop here, read(1) returns a length 1 string
character = chr(byte) # I'm not familiar with the serial module, but I think this isn't needed
if character == 'S':
# We check that we are not executing the task already, and if so we handle it accordingly
if thread:
print('Error: a task is already running!')
continue
# Start the task in a thread
stop_task.clear()
thread = threading.Thread(target=do_task)
thread.start()
elif character == 'K':
print('K received -> BREAK FROM TASK')
if thread:
stop_task.set()
thread = None
请记住,这样做一次只能处理一个任务,而且一般来说,你应该确保你启动的任何线程都能完成(在这个例子中,很明显它们最终会在设置事件后完成,但更复杂的执行可能会让线程陷入无限循环)。
这是一个小例子,但我希望它能帮助你朝着正确的方向前进。