在Python中使用超时运行一些代码的正确方法

zah*_*pov 30 python windows multithreading timeout

我在网上找了一些SO讨论和ActiveState配方来运行一些超时的代码.看起来有一些常见的方法:

  • 使用运行代码的线程,并join使用超时.如果超时已超时 - 终止该线程.这在Python(使用的私有_Thread__stop函数)中不是直接支持的,所以这是不好的做法
  • 使用signal.SIGALRM- 但这种方法不适用于Windows!
  • 使用带有超时的子进程- 但这太重了 - 如果我想经常启动可中断任务,我不希望每个进程都有火!

那么,正确的方法是什么?我不是在询问有关变通方法(例如使用Twisted和async IO),而是解决实际问题的实际方法 - 我有一些功能,我想只运行一些超时.如果超时,我想要控制回来.我希望它能在Linux和Windows上运行.

Mar*_*ill 9

您可能正在寻找的是多处理模块.如果subprocess太重,那么这可能也不适合您的需求.

import time
import multiprocessing

def do_this_other_thing_that_may_take_too_long(duration):
    time.sleep(duration)
    return 'done after sleeping {0} seconds.'.format(duration)

pool = multiprocessing.Pool(1)
print 'starting....'
res = pool.apply_async(do_this_other_thing_that_may_take_too_long, [8])
for timeout in range(1, 10):
    try:
        print '{0}: {1}'.format(duration, res.get(timeout))
    except multiprocessing.TimeoutError:
        print '{0}: timed out'.format(duration) 

print 'end'
Run Code Online (Sandbox Code Playgroud)

  • 如果您希望能够终止任意代码(包括C扩展)并且具有一些清理效果,则需要使用进程.如果您认为它们太慢而无法分叉,那么请保留一个或两个预生成的孩子等待您需要时执行."多处理"似乎就是这样做的,所以我用一个upvote替换我的答案. (2认同)

Mik*_*ham 9

一个完全通用的解决方案真的,老实说不存在.您必须为给定的域使用正确的解决方案.

  • 如果您希望完全控制代码的超时,则必须将其编写为合作.这样的代码必须能够以某种方式分解成小块,就像在事件驱动的系统中一样.你也可以通过线程来做到这一点,如果你可以确保没有任何东西会锁定太久,但处理锁定权利实际上是非常困难的.

  • 如果你想要超时,因为你害怕代码失控(例如,如果你担心用户会要求你的计算器计算9**(9**9)),你需要在另一个过程中运行它.这是充分隔离它的唯一简单方法.在事件系统或甚至不同的线程中运行它是不够的.也可以将其分解成与其他解决方案类似的小块,但需要非常小心的处理,通常是不值得的; 无论如何,这不允许你做与运行Python代码完全相同的事情.


NoB*_*ugs 5

如果与网络相关,则可以尝试:

import socket
socket.setdefaulttimeout(number)
Run Code Online (Sandbox Code Playgroud)