首页 > 解决方案 > 将 Python 函数返回组织到一个干净的 for 循环中并检查是否超过时间

问题描述

我有一个在多个数据帧上运行的函数。我希望能够更好地组织这个并添加一个超时语句。我对此有点陌生...

组织数据框 -

d = {}
dfs = [1,2,3]
for name in dfs:
   df[name] = some_function()

然后设置将它们组织成一个干净的循环,检查 df 运行的时间。所以它会运行df_1df_2因为它们需要 5 秒,但会跳过并打印df_3它需要 x 秒数。

def timeout():
   # check how long df_1, df_2, df_3 takes and if takes longer than 30 seconds then print out the df name

标签: pythonperformancefor-looptime

解决方案


您可以使用 Timer(来自 threading 模块),但您的循环必须合作并停止,然后时间到期。这也可以通过检查每次迭代的经过时间来完成,但我相信 Timer 方法会产生更少的开销。

假设您正在为循环使用迭代器,您可以定义一个通用的“timeOut”函数来强制它在给定的秒数后停止:

from threading import Timer

def timeout(maxTime,iterator):
    stop = False
    def timedOut(): # function called when timer expires
        nonlocal stop
        stop = True
    t = Timer(maxTime,timedOut)
    t.start()
    for r in iterator:
        if stop: break  # you could print the content of r here if needed.
        yield r
    t.cancel()

输出:

for i in timeout(3,range(1000)):
    for _ in range(10000000): pass
    print(i)

1
2
3
4
5
6
7
8     # it stopped here after 3 seconds with 992 iterations to go

在您的示例中,这可能是:

d = {}
dfs = [1,2,3]
for name in timeout(5,dfs):
   df[name] = some_function()

请注意,当总处理时间超过 5 秒时,这将停止循环,但如果超过总时间,dfs它不能中断内部正在发生的事情。some_funtion()

如果您需要一个不绑定到特定循环的超时,您可以创建一个存储在全局变量或单例类中的 Timer 实例,并在代码中的适当位置检查其状态:

t = Timer(25,lambda:pass) # timer will not do anything when expired
t.start()                 # but will no longer be alive after 25 seconds

...
    # at appropriate places in your code
    if not t.is_alive(): return  # or break or continue ...

推荐阅读