在Python中从另一个函数中中断函数执行

12 投票
3 回答
25998 浏览
提问于 2025-04-18 15:17

我有一个函数 a,它负责执行一些任务,还有另一个函数 b,它是用来处理一些事件的回调函数。每当发生某个事件时,函数 b 就会被调用,我希望它能够中断函数 a 的执行。这两个函数都是在同一个类里面定义的。

函数 a 不应该去调用函数 b。函数 b 是完全独立的,它是一个回调,用于处理来自 ROS(机器人操作系统)等外部事件,比如“检测到用户面孔”。

我需要的基本上就像在 Python 中调用 Ctrl+C 这样的功能,它可以中断一个特定的函数,而不是整个程序。

在 Python 中可以做到这一点吗?

3 个回答

0

我之前使用了线程。

    import threading
class myThread (threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        # Get lock to synchronize threads
        #threadLock.acquire()
        if self.name == 'a':
            function_a(self.name, self.counter, 3)
        if self.name == 'b':
            function_b(self.name, self.counter, 3)

def function_a(threadName, delay, counter):
    name = raw_input("Name")
    print name

def function_b(threadName, delay, counter):
    global thread1
    thread1.shutdown = True
    thread1._Thread__stop()

# Create new threads
thread1 = myThread(1, "a", 0)
thread2 = myThread(2, "b", 0)

# Start new Threads
thread1.start()
thread2.start()

当线程1停止时,function_a也停止执行了。

5

我会这样做:

  • 定义一个自定义的异常
  • 在合适的尝试/捕获块中调用回调函数
  • 如果回调函数决定要中断执行,它会抛出一个异常,调用者会捕获这个异常并根据需要处理它。

下面是一些伪代码:

class InterruptExecution (Exception):
    pass

def function_a():
    while some_condition_is_true():
        do_something()
        if callback_time():
            try:
                function_b()
            except InterruptExecution:
                break
        do_something_else()
    do_final_stuff()


def function_b():
    do_this_and_that()
    if interruption_needed():
        raise (InterruptExecution('Stop the damn thing'))
8

一般来说,不建议用异常来控制程序的流程。相反,可以看看Python标准库中的threading.Event,即使你只打算使用一个线程(其实最基本的Python程序至少也会用到一个线程)。

这个回答https://stackoverflow.com/a/46346184/914778很好地解释了一个函数(函数b)是如何打断另一个函数(函数a)的。

下面是从那个回答中总结的一些重要部分。

首先,设置你的线程库:

from threading import Event
global exit
exit = Event()

这个可以很好地替代time.sleep(60),因为它可以被打断:

exit.wait(60)

这段代码会一直执行,直到你把exit改成“set”:

while not exit.is_set():
    do_a_thing()

这将导致exit.wait(60)停止等待,同时exit.is_set()会返回True

exit.set()

这将再次启用执行,exit.is_set()会返回False

exit.clear()

撰写回答