怎么简单的限制一个函数的运行时间? try (in n seconds) 超时就 pass

2020-10-03 13:56:33 +08:00
 miniyao

由于在一个线程中接入了一个第三方服务,这个远程服务并不是很重要,远程调用线路和请求总有失败的可能。

因此,就想把这个函数放在 Try 中去运行:

try:

    do_something()

except:

    pass

由于每次 do_something() 会阻塞当前线程,所以想限制个最长执行时间,超时直接 pass 。

用 eventlet 有点偏重,有没有什么比较简单的实现优雅的实现方法?

3422 次点击
所在节点    Python
14 条回复
imn1
2020-10-03 13:58:23 +08:00
远程模块一般都有 timeout 异常的
Mitt
2020-10-03 13:58:53 +08:00
开线程超时然后强制终止?
kangsheng9527
2020-10-03 13:59:27 +08:00
python 不知道,go 可以使用 context 包去处理。。。
JeffGe
2020-10-03 14:01:49 +08:00
新建进程超时就 kill 可行吗
dbow
2020-10-03 14:08:41 +08:00
这种得用协程要搞, python3 里边有 async, await, 前提是你使用的库支持这么操作.
infun
2020-10-03 14:09:50 +08:00
试试 retrying 库
ClericPy
2020-10-03 14:30:37 +08:00
线程差就差在没法外部强制停止, 所以这种场景我都是协程跑的, 外部超时直接发送 cancel 指令

至于远程调用相关的, 一般会有超时控制吧, 具体看你 do 了什么 thing 了
MoYi123
2020-10-03 14:37:27 +08:00
@contextmanager
def timeout_signal(second):
____signal.signal(signal.SIGALRM, raise_timeout)
____signal.alarm(second)
____try:
________yield
____finally:
________signal.signal(signal.SIGALRM, signal.SIG_IGN)


def raise_timeout(_signum, _frame):
____raise TimeoutError


def timeout(second):
____def _timeout(fun):
________@wraps(fun)
________def _fun(*args, **kwargs):
____________with timeout_signal(second):
________________return fun(*args, **kwargs)

________return _fun

____return _timeout


@timeout(1)
def f():
____pass


我平时的用脚本里是这样写的,性能好坏不确定。
MiracleKagari
2020-10-03 18:24:06 +08:00
rxpy 应该有
MiracleKagari
2020-10-03 20:12:02 +08:00
@MiracleKagari 创建一个响应式对象,然后找一个合适的操作符,然后...
tkmiles
2020-10-03 20:49:07 +08:00
使用 future 呀
一个线程结束之后更新 future
另外一个线程在 future 上等待, future 上可以加 timeout 的
然后另外一个线程在 timeout 之后直接终止子线程

python 终止子线程有点限制, 只能发送线程异步异常去终止 python 代码执行, 如果你卡在 C 级别的代码, 那只能等待
回调回 python 代码的时候, 异步异常才能终止线程

如果你想终止线程更严格一点, 比如终止 C 代码, 那么只能求助于系统中断了
itskingname
2020-10-03 21:11:17 +08:00
如果是 macOS 和 Linux,我写过一篇文章来说明: https://mp.weixin.qq.com/s/PUcHuJMG5Mk2tWWzYeq2wQ
l4ever
2020-10-04 02:33:47 +08:00
import multiprocessing as mp
def pool_funcs(func, args=(), kwds=None, timeout=1, default=None):
"""
线程超时
@param func:
@param args:
@param kwds:
@param timeout:
@param default:
@return:
"""

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
namelosw
2020-10-04 03:43:06 +08:00
这个和停机问题相关,如果语言没有提供特殊的机制的话一般要靠子进程+监护的形式,因为停机是没法本地恢复的。像大量应用这种模式的 Erlang,也是尽量通过把进程做得超级轻量化,然后用同样的方式实现的。

还有一些形式就是自己写一个简单的类似解释器的东西,你重新发明并嵌入一个语言,这个语言的解释归你管,就可以在每个求值周期都检查一次 timeout 。类似的例子比较像 React fiber —— 不过 fiber 只能管 React 渲染,而不能管 JavaScript 执行,也就是说这种 timeout 就 kill 掉的机制只能对 React 自己的 DSL ( JSX 以及 Element 的 Rendering )成立,而对 JavaScript 没有普适性,除非重新实现一遍 JavaScript,或者启另外一个 JavaScript 进程。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/712349

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX