2012-04-14 31 views
17

我必须在python中执行一段程序,它需要执行一段时间,然后(执行时无所谓)它必须将信息转储到文件,关闭文件,然后退出。推迟代码以便以后在python中执行(像javascript中的setTimeout)

这里的行为在JavaScript中等同于使用setTimeout(func, 1000000),其中第一个参数(func)是指向具有退出代码的函数的指针,其第二个参数是程序可执行的时间。

我知道这个程序在C(使用SO信号)进行,但与Python

+0

这不是'setTimeout'在JavaScript中的作用。这样做是为了稍后排队执行一个函数(即一旦超时已过)。 – 2012-04-14 15:43:07

+1

是啊......你说得对。但我只想给我想要的东西,我没有发现需要在技术上完全正确。 – brunoais 2012-04-14 15:47:38

+0

你可以做的最好的事情是用线程模拟一些东西。 – 2012-04-14 15:58:11

回答

34

实际上,Timer可能是实现您想要的最简单的方法。

此代码将执行下列操作:

  • 后1秒,它打印 “ARG1 ARG2”
  • 2秒后,它打印 “OWLS OWLS OWLS”

===

from threading import Timer 

def twoArgs(arg1,arg2): 
    print arg1 
    print arg2 
    print "" 

def nArgs(*args): 
    for each in args: 
     print each 

#arguments: 
#how long to wait (in seconds), 
#what function to call, 
#what gets passed in 
r = Timer(1.0, twoArgs, ("arg1","arg2")) 
s = Timer(2.0, nArgs, ("OWLS","OWLS","OWLS")) 

r.start() 
s.start() 

===

上面的代码很可能会解决您的问题。

但是!还有另一种方法,那就是不使用多线程。它更像Javascript,它是单线程的。

对于这个单线程版本,您所需要做的就是将函数及其参数存储在一个对象中,以及该函数应该运行的时间。

一旦你有包含函数调用和超时的对象,只要定期检查函数是否准备好执行。

正确的做法是让priority queue存储我们将来要运行的所有功能,如下面的代码所示。

就像在Javascript中一样,这种方法不能保证函数能够准确地按时运行。一个需要很长时间才能运行的函数会延迟它后面的函数。但它确实保证了一个函数将会比其超时运行更快

此代码将执行下列操作:

  • 后1秒,它打印 “20”
  • 2秒后,它打印 “132”
  • 3秒钟之后,它退出。

===

from datetime import datetime, timedelta 
import heapq 

# just holds a function, its arguments, and when we want it to execute. 
class TimeoutFunction: 
    def __init__(self, function, timeout, *args): 
     self.function = function 
     self.args = args 
     self.startTime = datetime.now() + timedelta(0,0,0,timeout) 

    def execute(self): 
     self.function(*self.args) 

# A "todo" list for all the TimeoutFunctions we want to execute in the future 
# They are sorted in the order they should be executed, thanks to heapq 
class TodoList: 
    def __init__(self): 
     self.todo = [] 

    def addToList(self, tFunction): 
     heapq.heappush(self.todo, (tFunction.startTime, tFunction)) 

    def executeReadyFunctions(self): 
     if len(self.todo) > 0: 
      tFunction = heapq.heappop(self.todo)[1] 
      while tFunction and datetime.now() > tFunction.startTime: 
       #execute all the functions that are ready 
       tFunction.execute() 
       if len(self.todo) > 0: 
        tFunction = heapq.heappop(self.todo)[1] 
       else: 
        tFunction = None      
      if tFunction: 
       #this one's not ready yet, push it back on 
       heapq.heappush(self.todo, (tFunction.startTime, tFunction)) 

def singleArgFunction(x): 
    print str(x) 

def multiArgFunction(x, y): 
    #Demonstration of passing multiple-argument functions 
    print str(x*y) 

# Make some TimeoutFunction objects 
# timeout is in milliseconds 
a = TimeoutFunction(singleArgFunction, 1000, 20) 
b = TimeoutFunction(multiArgFunction, 2000, *(11,12)) 
c = TimeoutFunction(quit, 3000, None) 

todoList = TodoList() 
todoList.addToList(a) 
todoList.addToList(b) 
todoList.addToList(c) 

while True: 
    todoList.executeReadyFunctions() 

===

在实践中,你可能会有更多的事情在不仅仅是检查while循环,如果你超时功能都准备好了。您可能正在轮询用户输入,控制某些硬件,读取数据等。

11

您可以使用蟒蛇,以及信号(仅适用于UNIX)

import signal, sys 

# install a SIGALRM handler 

def handler(signum, frame): 
    print "got signal, exiting" 
    sys.exit(1) 

signal.signal(signal.SIGALRM, handler) 

# emit SIGALRM after 5 secs 

signal.setitimer(signal.ITIMER_REAL, 5) 

# do stuff 

i = 1 
while True: 
    if i % 100000 == 0: 
     print i 
    i += 1 

文档:http://docs.python.org/library/signal.html

+0

什么与Windows和Linux兼容? (我需要它兼容) – brunoais 2012-04-14 15:48:06

+5

不知道。也许可以使用http://docs.python.org/library/threading.html#timer-objects。 – georg 2012-04-14 16:12:13

+2

@ thg435我测试过了。以上评论应该是被接受的答案。 – 2012-07-11 09:14:45

相关问题