programing

정기 작업 실행

bestprogram 2023. 5. 22. 21:53

정기 작업 실행

저는 Windows에서 일하고 있습니다.는 함수 함를실니수합을 .foo()10초마다
이거 어떻게 하는 거지?

에의 foo()을 생성합니다.Timer어느 쪽인가 하면foo()10초 후에 자동으로 작동합니다.
왜면냐,Timer새로운 것을 창조합니다.thread을 부르다foo().
당신은 차단되지 않고 다른 일을 할 수 있습니다.

import time, threading
def foo():
    print(time.ctime())
    threading.Timer(10, foo).start()

foo()

#output:
#Thu Dec 22 14:46:08 2011
#Thu Dec 22 14:46:18 2011
#Thu Dec 22 14:46:28 2011
#Thu Dec 22 14:46:38 2011

10초만 사용하면 됩니다.threading.Timer(10,foo)시작 시간 드리프트가 발생합니다. (이 문제는 사용자가 신경 쓰지 않거나 사용자의 정확한 상황에 따라 중요한 문제의 원인이 될 수 있습니다.)스레드의 웨이크업 시간 또는 기능의 실행 시간이 부정확한 두 가지 원인이 있을 수 있습니다.

이 게시물의 마지막 부분에서 일부 결과를 볼 수 있지만, 먼저 수정 방법에 대한 예를 볼 수 있습니다.실제로 호출된 시간과 반대로 다음에 함수를 호출해야 할 때를 추적하고 그 차이를 설명해야 합니다.

다음은 약간 표류하는 버전입니다.

import datetime, threading

def foo():
    print datetime.datetime.now()
    threading.Timer(1, foo).start()

foo()

출력은 다음과 같습니다.

2013-08-12 13:05:36.483580
2013-08-12 13:05:37.484931
2013-08-12 13:05:38.485505
2013-08-12 13:05:39.486945
2013-08-12 13:05:40.488386
2013-08-12 13:05:41.489819
2013-08-12 13:05:42.491202
2013-08-12 13:05:43.492486
2013-08-12 13:05:44.493865
2013-08-12 13:05:45.494987
2013-08-12 13:05:46.496479
2013-08-12 13:05:47.497824
2013-08-12 13:05:48.499286
2013-08-12 13:05:49.500232

1초 미만의 카운트가 지속적으로 증가하여 시작 시간이 "드리프트" 상태임을 알 수 있습니다.

다음은 드리프트를 올바르게 설명하는 코드입니다.

import datetime, threading, time

next_call = time.time()

def foo():
  global next_call
  print datetime.datetime.now()
  next_call = next_call+1
  threading.Timer( next_call - time.time(), foo ).start()

foo()

출력은 다음과 같습니다.

2013-08-12 13:21:45.292565
2013-08-12 13:21:47.293000
2013-08-12 13:21:48.293939
2013-08-12 13:21:49.293327
2013-08-12 13:21:50.293883
2013-08-12 13:21:51.293070
2013-08-12 13:21:52.293393

여기서 더 이상 1초 미만의 시간이 증가하지 않음을 알 수 있습니다.

이벤트가 매우 자주 발생하는 경우 각 이벤트에 대해 새 스레드를 시작하는 대신 단일 스레드에서 타이머를 실행할 수 있습니다.드리프트를 고려할 때 이는 다음과 같습니다.

import datetime, threading, time

def foo():
    next_call = time.time()
    while True:
        print datetime.datetime.now()
        next_call = next_call+1;
        time.sleep(next_call - time.time())

timerThread = threading.Thread(target=foo)
timerThread.start()

그러나 응용 프로그램이 정상적으로 종료되지 않는 경우 타이머 스레드를 종료해야 합니다.스레드를 수동으로 죽이지 않고 응용 프로그램이 완료되었을 때 정상적으로 종료하려면 다음을 사용해야 합니다.

timerThread = threading.Thread(target=foo)
timerThread.daemon = True
timerThread.start()

타이밍을 맞추기 위해 제너레이터를 사용하여 솔루션을 찾지 못해 놀랐습니다.저는 단지 제 목적을 위해 이것을 디자인했을 뿐입니다.

은 싱글 마다 객체 시간에 하고, 록 하게 조정합니다.time모듈(스택 교환에서 시도한 여러 솔루션과 달리).

참고: Python 2.x의 경우 대체next(g)로 아래에g.next().

import time

def do_every(period,f,*args):
    def g_tick():
        t = time.time()
        while True:
            t += period
            yield max(t - time.time(),0)
    g = g_tick()
    while True:
        time.sleep(next(g))
        f(*args)

def hello(s):
    print('hello {} ({:.4f})'.format(s,time.time()))
    time.sleep(.3)

do_every(1,hello,'foo')

결과는 다음과 같습니다.

hello foo (1421705487.5811)
hello foo (1421705488.5811)
hello foo (1421705489.5809)
hello foo (1421705490.5830)
hello foo (1421705491.5803)
hello foo (1421705492.5808)
hello foo (1421705493.5811)
hello foo (1421705494.5811)
hello foo (1421705495.5810)
hello foo (1421705496.5811)
hello foo (1421705497.5810)
hello foo (1421705498.5810)
hello foo (1421705499.5809)
hello foo (1421705500.5811)
hello foo (1421705501.5811)
hello foo (1421705502.5811)
hello foo (1421705503.5810)

이 예제에는 각 주기에 대해 0.3초 동안 CPU가 다른 작업을 수행하는 시뮬레이션이 포함되어 있습니다.매번 임의로 변경하면 문제가 되지 않습니다.의 최대치yield보호하는 역할을 하는 선sleep호출되는 함수가 지정된 기간보다 오래 걸리는 경우 음수에서 시작합니다.이 경우 즉시 실행되고 다음 실행 타이밍에서 손실된 시간을 보충합니다.

아마도 예약된 모듈이 귀하의 요구를 충족시킬 것입니다.

또는 Timer 개체를 사용하는 것을 고려합니다.

이렇게 하면 모든 통화 사이에 10초의 수면 시간이 삽입됩니다.foo()이는 통화가 빨리 완료될 때 요청한 대략적인 값입니다.

import time

while True:
    foo()
    time.sleep(10)

당신의 시간 동안 다른 것들을 하는 것.foo()백그라운드 스레드에서 호출 중입니다.

import time
import sys
import threading

def foo():
    sys.stdout.write('({}) foo\n'.format(time.ctime()))

def foo_target():
    while True:
        foo()
        time.sleep(10)

t = threading.Thread(target=foo_target)
t.daemon = True
t.start()
print('doing other things...')

스레드 클래스를 사용하는 좋은 구현은 다음과 같습니다. http://g-off.net/software/a-python-repeatable-threadingtimer-class

아래 코드는 조금 더 빠르고 더럽습니다.

from threading import Timer
from time import sleep

def hello():
    print "hello, world"
    t = Timer(3,hello)
    t.start()

t = Timer(3, hello)
t.start() # after 3 seconds, "hello, world" will be printed

# timer will wake up ever 3 seconds, while we do something else
while True:
    print "do something else"
    sleep(10)

다른 스레드에서 작업을 실행할 수 있습니다. threading.Timer예를 들어 콜백이 반환되는 한 작업을 실행하려는 경우 시간이 경과한 후 지정된 콜백을 한 번 실행할 수 있습니다.True(실제로 이것이 무엇입니까?glib.timeout_add를 제공하지만 Windows에 설치되어 있지 않을 수 있습니다.) 또는 이를 취소할 때까지 다음 코드를 사용할 수 있습니다.

import logging, threading, functools
import time

logging.basicConfig(level=logging.NOTSET,
                    format='%(threadName)s %(message)s')

class PeriodicTimer(object):
    def __init__(self, interval, callback):
        self.interval = interval

        @functools.wraps(callback)
        def wrapper(*args, **kwargs):
            result = callback(*args, **kwargs)
            if result:
                self.thread = threading.Timer(self.interval,
                                              self.callback)
                self.thread.start()

        self.callback = wrapper

    def start(self):
        self.thread = threading.Timer(self.interval, self.callback)
        self.thread.start()

    def cancel(self):
        self.thread.cancel()


def foo():
    logging.info('Doing some work...')
    return True

timer = PeriodicTimer(1, foo)
timer.start()

for i in range(2):
    time.sleep(2)
    logging.info('Doing some other work...')

timer.cancel()

출력 예:

Thread-1 Doing some work...
Thread-2 Doing some work...
MainThread Doing some other work...
Thread-3 Doing some work...
Thread-4 Doing some work...
MainThread Doing some other work...

참고: 콜백은 간격 실행 시마다 실행되지 않습니다.간격은 스레드가 마지막으로 완료된 콜백과 다음 번 호출 사이에 대기하는 시간입니다.

다음은 드리프트를 감지할 때 자동으로 수정하는 간단한 스레드 슬립 기반 버전입니다.

참고: 이는 다음 3가지 합리적인 가정이 충족되는 경우에만 작동합니다.

  1. 기간이 실행 중인 함수의 실행 시간보다 훨씬 큽니다.
  2. 실행 중인 기능은 각 통화에서 거의 동일한 시간이 소요됩니다.
  3. 통화 간 드리프트 양이 1초 미만입니다.

-

from datetime import timedelta
from datetime import datetime

def exec_every_n_seconds(n,f):
    first_called=datetime.now()
    f()
    num_calls=1
    drift=timedelta()
    time_period=timedelta(seconds=n)
    while 1:
        time.sleep(n-drift.microseconds/1000000.0)
        current_time = datetime.now()
        f()
        num_calls += 1
        difference = current_time - first_called
        drift = difference - time_period* num_calls
        print "drift=",drift

만약 당신이 10초마다 파이썬 스크립트 안에서 foo()를 실행하려고 했다면, 당신은 이 라인들에서 무언가를 할 수 있습니다.

import time

def foo():
    print "Howdy"

while True:
    foo()
    time.sleep(10)

언급URL : https://stackoverflow.com/questions/8600161/executing-periodic-actions