53

しばらく実行する必要があるプログラムをPythonで実行する必要があり、その後(実行場所は関係ありません)情報をファイルにダンプし、ファイルを閉じてから終了する必要があります。

ここでの動作はsetTimeout(func, 1000000)、最初のパラメーター (func) が終了コードを含む関数へのポインターであり、2 番目のパラメーターがプログラムの実行に使用できる時間である場合の JavaScript での使用と同等です。

このプログラムを C (SO シグナルを使用) で作成する方法を知っていますが、Python を使用します。

4

4 に答える 4

82

実際には、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 のように機能します。

このシングル スレッド バージョンでは、関数とその引数を、関数を実行する時刻と共にオブジェクトに格納するだけです。

関数呼び出しとタイムアウトを含むオブジェクトを取得したら、関数を実行する準備ができているかどうかを定期的に確認します。

これを行う正しい方法は、以下のコードに示すように、将来実行するすべての関数を格納する優先キューを作成することです。

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 ループでさらに多くのことが行われる可能性があります。ユーザー入力のポーリング、一部のハードウェアの制御、データの読み取りなどを行っている可能性があります。

于 2013-03-17T02:02:43.970 に答える
12

Pythonでもシグナルを使用できます(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

于 2012-04-14T15:45:33.303 に答える