Подтвердить что ты не робот

Отложить код для последующего выполнения в python (например, setTimeout в javascript)

Мне нужно сделать программу на python, которая должна выполняться в течение некоторого времени и затем (не имеет значения, где она выполняется), она должна вывести информацию в файл, закрыть файл и затем выйти.

Поведение здесь эквивалентно в JavaScript с использованием setTimeout(func, 1000000), где его первый параметр (func) будет указателем на функцию с кодом выхода, а вторым параметром будет время, доступное для выполняемой программы.

Я знаю, как сделать эту программу на C (используя SO-сигналы), но с python

4b9b3361

Ответ 1

На практике 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 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()

===

На практике у вас, вероятно, будет больше возможностей в этом цикле, чем просто проверка того, готовы ли ваши функции тайм-аута. Вы можете проводить опрос для ввода пользователем, управлять некоторым оборудованием, считывать данные и т.д.

Ответ 2

Вы также можете использовать сигналы в 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

Ответ 3

В Python 3 есть хорошее решение с использованием asyncio:

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

Обратите внимание, что функции сна и аналогичные функции в Python ожидают несколько секунд, поэтому я повторил это. Но вы можете поставить дроби, если вам нужны миллисекунды. (например, 0,5 => 500 мс).

Преимущество этого подхода перед asyncio.call_later заключается в том, что он работает только с синхронным обратным вызовом. Эта реализация awaits если обратный вызов является сопрограммой, поэтому он немного более устойчив.

Ответ 4

Вы можете использовать call_later метод цикла событий python3 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())

Ответ 5

Используйте модуль time следующим образом:

import time
time.sleep(100)#in seconds
somefunction()