在X秒内调用函数

时间:2013-03-17 12:37:10

标签: python

在一个函数中,我想每2秒调用一行。每当我使用睡眠功能时,代码等待2秒然后转到下一条指令。但是,我希望每2秒调用一次函数,而不会打扰其他指令。实施例;

a = None
def foo():
    bar()

    a = a * 12 
    print "A : ",a

def bar():
    a = 0

每两秒钟,应该重置一次。但是,在两秒钟内,应该增加和显示a的值。可能吗 ?怎么样?

3 个答案:

答案 0 :(得分:2)

您可以轮询时间。这是读取当前时间,存储它,处理你的东西然后忙等待直到当前时间与存储的时间+ 2秒相匹配。如果你愿意,可以在你的东西之后加一个睡眠。但请确保在2秒间隔过期之前完成睡眠。例如。只睡了1.5秒。

如果您想独立运行它,则需要使用线程。 http://docs.python.org/2/library/threading.html

您可能还想在这里考虑答案: Executing periodic actions in Python

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

答案 1 :(得分:2)

使用threading.Timer。但只是在单独的计时器中运行代码中的bar将无效,您必须首先考虑在线程之间使用变量。

答案 2 :(得分:0)

我会使用线程和锁来满足您的需求。

事实上,我喜欢由我的朋友Pepe编写的开源ThreadPool。

这是ThreadPool代码,之后是一个可能的解决方案:

#! /usr/bin/python
# -*- coding: utf-8 -*-
# File: threadPool.py

import threading
import Queue
import time
import sys
import traceback
import datetime

Instance = None

def getInstance():
    global Instance
    if not Instance:
        Instance = ThreadPool()
    return Instance


class ThreadPool:
    def __init__(self,maxWorkers = 10):
        self.tasks = Queue.Queue()
        self.workers = 0
        self.working = 0
        self.maxWorkers = maxWorkers
        self.allKilled = threading.Event()
        self.countLock = threading.RLock()
        self.timers = {}
        self.timersLock = threading.Lock()
        self.timersThreadLock = threading.Lock()
        self.timersEvent = threading.Event()
        self.allKilled.set()

    def run(self,target,callback = None, *args, **kargs):
        """ starts task.
            target = callable to run with *args and **kargs arguments.
            callback = callable executed when target ends
                       callback sould accept one parameter where target's
                       return value is passed.
                       If callback is None it's ignored.
        """
        self.countLock.acquire()
        if not self.workers:
            self.addWorker()
        self.countLock.release()
        self.tasks.put((target,callback,args,kargs))

    def setMaxWorkers(self,num):
        """ Sets the maximum workers to create.
            num = max workers
                  If number passed is lower than active workers 
                  it will kill workers to match that number. 
        """
        self.countLock.acquire()
        self.maxWorkers = num
        if self.workers > self.maxWorkers:
            self.killWorker(self.workers - self.maxWorkers)
        self.countLock.release()

    def addWorker(self,num = 1):
        """ Add workers.
            num = number of workers to create/add.
        """
        for x in xrange(num):
            self.countLock.acquire()
            self.workers += 1
            self.allKilled.clear()
            self.countLock.release()        
            t = threading.Thread(target = self.__workerThread)
            t.setDaemon(True)
            t.start()

    def killWorker(self,num = 1):
        """ Kill workers.
            num = number of workers to kill.
        """
        self.countLock.acquire()
        if num > self.workers:
            num = self.workers
        self.countLock.release()
        for x in xrange(num):
            self.tasks.put("exit")            

    def killAllWorkers(self,wait = None):
        """ Kill all active workers.
            wait = seconds to wait until last worker ends
                   if None it waits forever.
        """

        self.countLock.acquire()
        self.killWorker(self.workers)
        self.countLock.release()
        self.allKilled.wait(wait)

    def __workerThread(self):
        while True:
            task = self.tasks.get()
            # exit is "special" tasks to kill thread
            if task == "exit":
                break

            self.countLock.acquire()
            self.working += 1
            if (self.working >= self.workers) and (self.workers < self.maxWorkers): # create thread on demand
                self.addWorker()
            self.countLock.release()

            fun,cb,args,kargs = task
            try:
                ret = fun(*args,**kargs)
                if cb:
                    cb(ret)
            except:
                ty,val,tb = sys.exc_info()
                print "Thread Catch:%s" % "".join(traceback.format_exception(ty,val,tb))

            self.countLock.acquire()
            self.working -= 1
            self.countLock.release()                
            del(fun) # Dereference all
            del(cb)
            del(args)
            del(kargs)
            del(task)

        self.countLock.acquire()
        self.workers -= 1
        if not self.workers:
            self.allKilled.set()
        self.countLock.release()

    def timer(self, cb, period):
        """ Add or remove timers.
            cb = callback function.
            period = period in seconds (float)
                     if period is 0 timer is deleted.
        """ 
        self.run(self.__timerThread, None, cb, period) 

    def __timerThread(self, cb, period):
        self.timersLock.acquire()
        self.timersEvent.set()
        if not period:
            if cb in self.timers:
                del(self.timers[cb])
            self.timersLock.release()
            return

        self.timers[cb] = [period,time.time()]    
        self.timersLock.release()

        if not self.timersThreadLock.acquire(0):
            return

        while True:
            self.timersLock.acquire()
            if len(self.timers) == 0:
                self.timersThreadLock.release()
                self.timersLock.release()
                break

            minWait = 30*24*3600
            now = time.time()
            for k,v in self.timers.items():
                period, last = v
                wait = period - (now - last)
                if wait <=0:
                    self.run(k)
                    wait = period
                    v[1] = now
                if wait < minWait:
                    minWait = wait
            self.timersLock.release()
            self.timersEvent.wait(minWait)
            self.timersEvent.clear()         

可能的解决方案:

#! /usr/bin/python
# -*- coding: utf-8 -*-
# File: a.py

import threadPool
import time
import threading

class A:
    def __init__(self):
        self.a = 1
        self.alock = threading.Lock()
        self.tp = threadPool.getInstance()

    def bar(self):
        self.alock.acquire()
        self.a = 1
        self.alock.release()

    def foo(self):
        self.tp.timer(self.bar, 2)
        while True:
            self.alock.acquire()
            self.a = self.a * 12 
            self.alock.release()
            print "A : ",self.a
            time.sleep(0.1)

a = A()
a.foo()

执行命令

$ python a.py