2012-04-14 32 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

相關問題