Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中执行pool.map时,是否可以每隔x秒执行一次函数?_Python_Pool_Python Multithreading - Fatal编程技术网

在python中执行pool.map时,是否可以每隔x秒执行一次函数?

在python中执行pool.map时,是否可以每隔x秒执行一次函数?,python,pool,python-multithreading,Python,Pool,Python Multithreading,我正在大数据阵列上运行pool.map,我想每分钟在控制台中打印一次报告。 可能吗?据我所知,python是同步语言,它不能像nodejs那样做到这一点 也许可以通过线程来实现。。或者如何 finished = 0 def make_job(): sleep(1) global finished finished += 1 # I want to call this function every minute def display_status(): print '

我正在大数据阵列上运行pool.map,我想每分钟在控制台中打印一次报告。 可能吗?据我所知,python是同步语言,它不能像nodejs那样做到这一点

也许可以通过线程来实现。。或者如何

finished = 0

def make_job():
   sleep(1)
   global finished
   finished += 1

# I want to call this function every minute
def display_status():
   print 'finished: ' + finished

def main():
    data = [...]
    pool = ThreadPool(45)
    results = pool.map(make_job, data)
    pool.close()
    pool.join()

考虑使用
时间
模块。
time.time()
函数返回当前值

例如,立即调用
time.time()
将返回
1410384038.967499
。一秒钟后,它将返回
1410384039.967499

我这样做的方法是使用while循环代替
results=pool(…)
,并在每次迭代中运行如下检查:

last_time = time.time()
while (...):
    new_time = time.time()
    if new_time > last_time+60:
        print "status update" + ...
        last_time = new_time
    (your computation here)
因此,这将检查自上次状态更新以来是否(至少)已过一分钟。它应该大约每六十秒打印一次状态更新


很抱歉,这是一个不完整的答案,但我希望这对您有所帮助或提供一些有用的想法。

一种方法是使用主线程作为监视线程。下面这样的方法应该可以工作:

def main():
   data = [...]
   results = []
   step = 0
   pool = ThreadPool(16)
   pool.map_async(make_job, data, callback=results.extend)
   pool.close()
   while True:
      if results:
          break
      step += 1
      sleep(1)
      if step % 60 == 0:
          print "status update" + ...
我使用了
.map()
而不是
.map\u async()
,因为前者是同步的。此外,您可能还需要替换
结果。使用更高效的方法扩展
。最后,由于GIL,速度提升可能比预期的要小得多


顺便说一句,您在一个关于ThreadPool;)的问题中写道Python是同步的,这有点可笑

您可以使用永久线程计时器,如以下问题中的计时器:

基本上,这只是一个
Timer
对象的包装器,它在每次调用所需函数时创建一个新的
Timer
对象。不要期望它的精度达到毫秒(甚至接近毫秒),但对于您的目的来说,它应该是理想的

使用此示例,您的示例将变成:

finished = 0

def make_job():
   sleep(1)
   global finished
   finished += 1

def display_status():
   print 'finished: ' + finished

def main():
    data = [...]
    pool = ThreadPool(45)

    # set up the monitor to make run the function every minute
    monitor = PerpetualTimer(60,display_status)
    monitor.start()
    results = pool.map(make_job, data)
    pool.close()
    pool.join()
    monitor.cancel()
编辑

更清洁的解决方案可能是(由于以下评论):

然后在代码中:

def main():
    data = [...]
    pool = ThreadPool(45)
    stop_flag = Event()
    RepeatTimer(60,display_status,stop_flag).start()
    results = pool.map(make_job, data)
    pool.close()
    pool.join()
    stop_flag.set()

好主意,虽然你有比赛条件。如果在
执行
self.hFunction()
时调用
monitor.cancel()
.handleFunction()
仍将完全执行,因此它将创建下一个计时器线程,并且有效地永久化计时器将无限期地继续工作,从而阻止程序完成。@RoberT Yup,永久定时器可以通过多种线程安全的方式重做。我已经添加了一个补丁,希望能够得到你提到的具体比赛条件。看起来你关上了门,但打开了一扇窗户(尽管很小)。这次比赛是在
.start()
中进行的,需要相当严重的计算机过载。如果至少使用了一次永久化器实例。设置了self.stop,因此如果在
self.thread.start()
之后,一些重负载导致计时器()以某种方式启动,请等待给定的时间并执行到“if not self.stop.is设置:”,然后主线程执行
self.stop.clear()
。监视将在第一次迭代中消失。我甚至不想去想(不提calc)它是多么的不可修改,但考虑到这样一个事实,45个其他潜在的资源密集型线程并行工作可能会给它一点发生的机会。当然,只需在
.start()
中交换这两个调用就可以解决问题。另一件事是,如果您决定使用Events(),那么您链接的页面上会有更干净、更好的解决方案。此外,在这种情况下,实际上并不需要
事件
,因为代码并没有在任何地方等待它,所以简单的布尔标志将执行以下操作:job@RoberT我想我一定是瞎了!我完全没有找到我所联系的那个问题的公认答案。你说得对,好多了。
from threading import Event,Thread 

class RepeatTimer(Thread):
    def __init__(self, t, callback, event):
        Thread.__init__(self)
        self.stop = event
        self.wait_time = t
        self.callback = callback
        self.daemon = True

    def run(self):
        while not self.stop.wait(self.wait_time):
            self.callback()
def main():
    data = [...]
    pool = ThreadPool(45)
    stop_flag = Event()
    RepeatTimer(60,display_status,stop_flag).start()
    results = pool.map(make_job, data)
    pool.close()
    pool.join()
    stop_flag.set()