2012-04-14 37 views
17

Tôi phải làm một chương trình trong python cần thực thi trong một thời gian và sau đó (không quan trọng nó đang thực thi ở đâu). đóng tệp và sau đó thoát.Mã trì hoãn để thực hiện sau này trong python (như setTimeout trong javascript)

Hành vi ở đây tương đương với JavaScript khi sử dụng setTimeout(func, 1000000) trong đó thông số đầu tiên (func) sẽ là con trỏ tới hàm có mã thoát và tham số thứ hai sẽ là thời gian có sẵn cho chương trình để thực thi.

tôi biết làm thế nào để làm cho chương trình này trong C (sử dụng SO tín hiệu) nhưng với python

+0

Đó không phải là những gì 'setTimeout' thực hiện trong JavaScript. Điều đó có nghĩa là xếp hàng một hàm để thực thi sau này (tức là khi hết thời gian chờ). –

+1

Vâng ... Bạn nói đúng. Nhưng tôi chỉ muốn đưa ra ý tưởng về những gì tôi muốn mà tôi không thấy cần phải hoàn toàn chính xác về mặt kỹ thuật. – brunoais

+0

Tốt nhất bạn có thể làm là thử một cái gì đó với chủ đề. –

Trả lời

34

Trong thực tế, Timer có lẽ là cách đơn giản nhất để thực hiện những gì bạn muốn.

Mã này sẽ làm như sau:

  • Sau 1 giây, nó in "arg1 arg2"
  • Sau 2 giây, nó in "cú cú cú"

===

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() 

===

Mã trên sẽ rất có thể giải quyết được vấn đề của bạn.

Nhưng! Có cách khác, không sử dụng đa luồng. Nó hoạt động nhiều hơn như Javascript, đó là đơn luồng.

Đối với phiên bản một chuỗi này, tất cả những gì bạn cần làm là lưu trữ hàm và các đối số của hàm trong đối tượng, cùng với thời gian chạy hàm.

Khi bạn có đối tượng chứa lệnh gọi hàm và thời gian chờ, chỉ cần kiểm tra định kỳ xem chức năng đã sẵn sàng để thực thi hay chưa.

Cách đúng để thực hiện việc này là tạo một priority queue để lưu trữ tất cả các chức năng mà chúng tôi muốn chạy trong tương lai, như được hiển thị trong mã bên dưới.

Cũng giống như trong Javascript, cách tiếp cận này không đảm bảo rằng chức năng sẽ được chạy chính xác về thời gian. Một hàm cần một thời gian rất dài để chạy sẽ làm chậm các hàm sau nó. Nhưng nó đảm bảo rằng một chức năng sẽ được chạy không sớm hơn so với thời gian chờ của nó.

Mã này sẽ làm như sau:

  • Sau 1 giây, nó in "20"
  • Sau 2 giây, nó in "132"
  • Sau 3 giây, nó tha.

===

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() 

===

Trong thực tế, bạn có thể sẽ nhiều hơn xảy ra ở chỗ vòng lặp while hơn là chỉ kiểm tra nếu chức năng thời gian chờ của bạn đã sẵn sàng để đi. Bạn có thể đang bỏ phiếu cho đầu vào của người dùng, kiểm soát một số phần cứng, đọc dữ liệu, v.v.

11

Bạn có thể sử dụng các tín hiệu trong python cũng (unix chỉ)

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 

Documents: http://docs.python.org/library/signal.html

+0

Mọi thứ tương thích với windows và linux? (Tôi cần nó tương thích với cả hai) – brunoais

+5

Không có ý tưởng. Một cái gì đó như http://docs.python.org/library/threading.html#timer-objects có thể. – georg

+2

@ thg435 Tôi đã thử nghiệm. Nhận xét trên phải là câu trả lời được chấp nhận. –

Các vấn đề liên quan