推迟代码以便以后在python中执行(比如javascript中的setTimeout)

bru*_*ais 34 python

我有蟒蛇,需要执行一段时间,然后(不要紧,它正在执行),则必须转储信息保存到文件做一个程序,关闭该文件,然后退出.

这里的行为等同于JavaScript来使用setTimeout(func, 1000000),其中第一个参数(FUNC)将是一个指向与退出代码和它的第二个参数的函数将提供给所述程序执行的时间.

我知道如何用C语言创建这个程序(使用SO信号)但是使用python

nar*_*oom 53

在实践中,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()
Run Code Online (Sandbox Code Playgroud)

===

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

但!有另一种方法,不使用多线程.它更像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()
Run Code Online (Sandbox Code Playgroud)

===

在实践中,你可能会在while循环中继续进行更多操作,而不仅仅是检查你的超时功能是否准备就绪.您可能正在轮询用户输入,控制某些硬件,读取数据等.


geo*_*org 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
Run Code Online (Sandbox Code Playgroud)

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

  • 不知道.像http://docs.python.org/library/threading.html#timer-objects这样的东西也许. (5认同)
  • @ thg435我已经测试过了.以上评论应该是接受的答案. (2认同)

Jay*_*Are 9

asyncio在 python 3 中有一个很好的解决方案:

import asyncio

def async_call_later(seconds, callback):
    async def schedule():
        await asyncio.sleep(seconds)

        if asyncio.iscoroutinefunction(callback):
            await callback()
        else:
            callback()

    asyncio.ensure_future(schedule())

async def do_something_async():
    await asyncio.sleep(0.5)
    print('Now! async')

async def main():
    print('Scheduling...')

    async_call_later(3, do_something_async)
    async_call_later(3, lambda: print('Now!'))

    print('Waiting...')

    await asyncio.sleep(4)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)

请注意,python 中的 sleep 和类似函数需要几秒钟,所以我复制了它。但是如果您需要毫秒,您可以提供分数。(例如 0.5 => 500 毫秒)。

这种方法相对于asyncio.call_later 的一个优点是它只适用于同步回调。awaits 如果回调是协程,则此实现会稍微更健壮。


nur*_*tin 5

您可以使用call_laterpython3的asyncio事件循环的方法。下面的示例将正常工作。

import asyncio

loop = asyncio.get_event_loop()

def callback():
    print("callback")
    loop.call_later(1, callback)

loop.call_later(1, callback)

async def main():
    while True:
        await asyncio.sleep(1)

loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)