当前位置: 首页 > 面试题库 >

在python中使用线程的超时功能不起作用

何德寿
2023-03-14
问题内容

我发现了一个代码创建一个超时功能在这里,这似乎并没有工作。完整的测试代码如下:

def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
    import threading
    class InterruptableThread(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
            self.result = None

        def run(self):
            try:
                self.result = func(*args, **kwargs)
            except:
                self.result = default

    it = InterruptableThread()
    it.start()
    it.join(timeout_duration)
    if it.isAlive():
        return default
    else:
        return it.result


def foo():
    while True:
        pass

timeout(foo,timeout_duration=3)

预期的行为:代码在3秒内结束。问题出在哪儿?


问题答案:

一个线程不能优雅地杀死另一个线程,因此对于您当前的代码,它foo永远不会终止。(使用thread.daemon = TruePython程序时,仅保留守护程序线程将退出,但这不允许您在foo不终止主线程的情况下终止。)

有些人]试图使用信号来停止执行,但这在某些情况下可能不安全

如果可以修改foo,则有许多解决方案。例如,您可以检查是否threading.Event要退出while循环。

但是,如果您不能修改foo,则可以使用该multiprocessing模块在子进程中运行它,因为与线程不同,子进程可以终止。这是看起来的示例:

import time
import multiprocessing as mp

def foo(x = 1):
    cnt = 1
    while True:
        time.sleep(1)
        print(x, cnt)
        cnt += 1

def timeout(func, args = (), kwds = {}, timeout = 1, default = None):
    pool = mp.Pool(processes = 1)
    result = pool.apply_async(func, args = args, kwds = kwds)
    try:
        val = result.get(timeout = timeout)
    except mp.TimeoutError:
        pool.terminate()
        return default
    else:
        pool.close()
        pool.join()
        return val


if __name__ == '__main__':
    print(timeout(foo, kwds = {'x': 'Hi'}, timeout = 3, default = 'Bye'))
    print(timeout(foo, args = (2,), timeout = 2, default = 'Sayonara'))

产量

('Hi', 1)
('Hi', 2)
('Hi', 3)
Bye
(2, 1)
(2, 2)
Sayonara

请注意,这也有一些限制。

  • 子流程接收父流程变量的 副本 。如果您在子流程中修改变量,则 不会 影响父流程。如果您的函数func需要修改变量,则需要使用共享变量。

  • 参数(通过传递args)和关键字(kwds)必须是可腌制的。

  • 进程比线程更多的资源。通常,您只想在程序开始时创建一次多处理池。每次调用时都会timeout创建此函数Pool。这是必要的,因为我们需要pool.terminate()终止foo。也许有更好的方法,但是我还没有想到。



 类似资料:
  • 我不能让谷歌云功能运行超过60秒,即使超时设置为540秒!!有什么建议吗? 我将部署时的超时标志设置为--timeout=540,并且我知道该设置会通过,因为在GCP WEB UI中会显示540秒的超时设置。我还尝试通过GCP WEB UI手动编辑超时至540。但无论如何,我还是在大约62000毫秒后超过了最后期限。 我已经尝试了pub/sub和https方法作为func触发器,但是仍然在60度左

  • 问题内容: 我已经使用Spark建立了Word2Vec模型并将其另存为模型。现在,我想在另一个代码中将其用作脱机模型。我已经加载了模型,并用它来表示单词的向量(例如,Hello),并且效果很好。但是,我需要使用map在RDD中为许多单词调用它。 当我在地图函数中调用model.transform()时,它将引发以下错误: “似乎您正在尝试从广播引用SparkContext。”异常:您似乎正在尝试从

  • 问题内容: 我正在使用这种技术来加载数据。因此,我创建了以下解析函数: 存在的问题是,是在瞬间函数执行。它是正确的/错误吗?我该如何解决? 问题答案: 您需要改用。该只更新 后 的路线被改变。因此,您的代码应遵循以下原则:

  • 问题内容: 我正在学习Vue并在计算属性中使用箭头功能时遇到问题。 我的原始代码工作正常(请参见下面的代码段)。 但是,更改计算属性中的方法后,颜色不会更改(尽管turnRed值仍成功在true和false之间切换)。 这是我的代码: 我使用错误的语法吗? 问题答案: 您遇到此错误是因为箭头函数不会绑定到您要为其定义计算属性的vue实例。如果要使用箭头功能进行定义,也会发生同样的情况。 不要在实例

  • 问题内容: 我正在尝试使用opencv v 2.1创建图像,但出现此错误: AttributeError:“模块”对象没有属性“ CreateImage” 该代码是 问题答案: 您正在覆盖名称空间。仅使用,而不使用其他。

  • 问题内容: 我无法在Windows上为OpenCV(Python)自动完成工作。 根据此处的Abid的说明,我将cv2.pyd文件粘贴到C:\Python27 \ Lib \ site-packages中。 在Python代码中,我如下导入: 我还安装了numpy,它在站点包中创建了自己的文件夹,这与OpenCV不同(我直接将其粘贴到站点包中)。 使用此设置,即使调用OpenCV方法,代码也不会出