Python 如何构造代码,以便能够启动可以相互杀死/替换的任务
我有一个Python程序,可以执行以下操作: 1) 在com端口上无休止地等待命令字符 2) 在接收字符时,启动一个新线程来执行一段特定的代码 如果收到新命令,我需要做的是: 1) 杀死上一个线程 2) 推出一个新的 我到处读到这样做不是正确的方式。Python 如何构造代码,以便能够启动可以相互杀死/替换的任务,python,python-multithreading,Python,Python Multithreading,我有一个Python程序,可以执行以下操作: 1) 在com端口上无休止地等待命令字符 2) 在接收字符时,启动一个新线程来执行一段特定的代码 如果收到新命令,我需要做的是: 1) 杀死上一个线程 2) 推出一个新的 我到处读到这样做不是正确的方式。 如果知道我需要在同一个过程中执行此操作,那么我想我需要使用线程…我建议您使用两种不同的方法: 如果您的进程都是从一个函数内部调用的,则可以在第一个函数上调用 如果正在运行外部脚本,则可能需要 可能需要在单独的线程中运行串行端口。当它收到一个字节时
如果知道我需要在同一个过程中执行此操作,那么我想我需要使用线程…我建议您使用两种不同的方法:
- 如果您的进程都是从一个函数内部调用的,则可以在第一个函数上调用
- 如果正在运行外部脚本,则可能需要
- 可能需要在单独的线程中运行串行端口。当它收到一个字节时,将该字节放入队列中。让主程序循环并检查队列以决定如何处理它。在主程序中,您可以使用join终止线程并启动新线程。您可能还想查看线程池,看看它是否是您想要的
ser = serial.Serial("COM1", 9600)
que = queue.Queue()
def read_serial(com, q):
val = com.read(1)
q.put(val)
ser_th = threading.Thread(target=read_serial, args=(ser, que))
ser_th.start()
th = None
while True:
if not que.empty():
val = que.get()
if val == b"e":
break # quit
elif val == b"a":
if th is not None:
th.join(0) # Kill the previous function
th = threading.Thread(target=functionA)
th.start()
elif val == b"b":
if th is not None:
th.join(0) # Kill the previous function
th = threading.Thread(target=functionB)
th.start()
elif val == b"c":
if th is not None:
th.join(0) # Kill the previous thread (functionA)
th = threading.Thread(target=functionC)
th.start()
try:
ser.close()
th.join(0)
except:
pass
如果您正在创建和加入许多线程,那么您可能只需要有一个函数来检查要运行的命令
running = True
def run_options(option):
if option == 0:
print("Running Option 0")
elif option == 1:
print("Running Option 1")
else:
running = False
while running:
if not que.empty():
val = que.get()
run_options(val)
让我通过添加一个代码结构示例来更精确地回答我的问题 假设同步Function由于在内部等待特定事件而仍在运行,如果收到命令“c”,我需要停止Function并启动functionC
def functionA():
....
....
call a synchronous serviceA that can take several seconds even more to execute
....
....
def functionB():
....
....
call a synchronous serviceB that nearly returns immediately
....
....
def functionC():
....
....
call a synchronous serviceC
....
....
#-------------------
def launch_async_task(function):
t = threading.Thread(target=function, name="async")
t.setDaemon(True)
t.start()
#------main----------
while True:
try:
car = COM_port.read(1)
if car == "a":
launch_async_task(functionA)
elif car == "b":
launch_async_task(functionB)
elif car == "c":
launch_async_task(functionC)
好的,我最后使用了一段代码,它使用ctypes lib来提供某种终止线程函数。 我知道这不是一个干净的继续方式,但在我的例子中,线程没有共享资源,所以它不应该有任何影响 如果有帮助的话,下面是一段可以在网上轻松找到的代码:
def terminate_thread(thread):
"""Terminates a python thread from another thread.
:param thread: a threading.Thread instance
"""
if not thread.isAlive():
return
exc = ctypes.py_object(SystemExit)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
ctypes.c_long(thread.ident), exc)
if res == 0:
raise ValueError("nonexistent thread id")
elif res > 1:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
我不认为超时解决方案有什么意义,因为我不希望函数在一段时间后退出,但我希望它在调用另一个函数后退出。您是否尝试过多处理?否则,您可以调用第二个函数作为第一个函数中的最后一个语句。如果我不明白,你可以发布你的代码摘要吗?我只是在下面发布了一个例子。希望它现在更清楚。我觉得你的答案可以帮助我,但我不知道如何适应我的代码,我张贴后的具体情况。。。一个想法?你必须有一种方法杀死正在运行的函数,这样你才能结束线程。我改变了我发布的第一个选项,向你展示了它是如何工作的。我刚刚尝试了你的新建议,但我无法消除之前的线程。一旦收到新命令,它仍将继续运行。我不明白th.join(0)怎么会杀死任何函数……你必须想出一种杀死函数的方法。线程连接将在线程退出其运行方法(functo)时结束线程。有一些终止线程的方法,但不推荐使用。好的,这就是为什么联接(0)没有终止任何内容。我想做的是在收到命令后立即退出我的功能!我试图找到一种方法,在每个可终止函数中插入一些公共代码,比如在特定条件下可能退出的while循环。