如何保护自己避免可能无限挂起的不稳定库调用?

2024-04-29 10:43:31 发布

您现在位置:Python中文网/ 问答频道 /正文

假设您发现自己处于一个不幸的位置,依赖于一个性能较差的库。你的代码需要调用FlakyClient.call(),但有时该函数挂起的时间不可接受。在

如下所示,解决此问题的一种方法是将调用包装在自己的进程中,并使用join方法中的timeout参数来定义您愿意在FlakyClient上等待的最长时间。这提供了一个很好的保护,但是它也防止代码主体对调用的结果做出反应FlakyClient.call(). 我所知道的解决另一个问题(将结果放入代码主体)的唯一方法是使用一些繁琐的IPC技术。在

什么是处理这两个问题的干净和Python式的方法?如果库调用挂起,我想保护自己,并且能够在调用完成后使用结果。在

谢谢!在

from multiprocessing import Process
from flaky.library import FlakyClient


TIMEOUT_IN_SECS = 10

def make_flaky_call():
    result = FlakyClient.call()

proc = Process(target=make_flaky_call)
proc.start()
proc.join(TIMEOUT_IN_SECS)
if proc.is_alive():
    proc.terminate()
    raise Exception("Timeout during call to FlakyClient.call().")

Tags: 方法代码infromimport时间timeoutproc
2条回答

我无法与Python2.7交流,但是在Python3中,正确的方法是使用asyncio和{a1}的概念。在

import concurrent

def make_flaky_call():
    return FlakyClient.call()

timeout = 10

with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
    future = executor.submit(make_flaky_call) # get a future object
    try:
        result = await future.result(timeout = timeout)
    except concurrent.futures.TimeOutError:
        # if a timeout occurs on the call, do something
        result = None # default value

这相当像Python。您可以将其与代码主体集成。它正确地使用try-except进行错误处理。它有一个内置的超时。它只在Python3.5中工作(感谢await-但是改为yield from使其与Python3.4兼容)。在

不幸的是,对于Python2.7,正确的处理方法是执行当前的操作。在

如果您使用的是进程,我建议您使用Queue来处理结果传输,并间接地管理函数超时。在

from multiprocessing import Process, Queue
from flaky.library import FlakyClient
import time

TIMEOUT_IN_SECS = 10

def make_flaky_call(queue):
    result = FlakyClient.call()
    queue.put(result)
    queue.put('END')

q = Queue()
proc = Process(target=make_flaky_call, args=(q,))
proc.start()
content = 0
result = None
while content != 'END':
    try:
        content = q.get(timeout=TIMEOUT_IN_SECS)
        if content != 'END':
            result = content
    except Empty:
        proc.terminate()
        raise Exception("Timeout during call to FlakyClient.call().")

相关问题 更多 >