免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4673 | 回复: 2
打印 上一主题 下一主题

【timer】一个疑似线程的问题,百思不得其解【已解决】 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-08-27 01:57 |只看该作者 |倒序浏览
本帖最后由 wfnh 于 2013-08-27 20:24 编辑

写了个timer类,发现每次都会多启动一个timer,一次比一次多,看得我十分不明白,求解答,代码和log在下面:
TaskManager:
  1. #coding=gb2312
  2. #-------------------------------------------------------------------------------
  3. # Name:        模块1
  4. # Purpose:
  5. #
  6. # Author:      Administrator
  7. #
  8. # Created:     02/03/2012
  9. # Copyright:   (c) Administrator 2012
  10. # Licence:     <your licence>
  11. #-------------------------------------------------------------------------------
  12. #!/usr/bin/env python
  13. import os
  14. import sys
  15. import time
  16. from event import eventDispatch
  17. #from common.singleton import Singleton #--单例模式
  18. from common import config
  19. from common.shareData import ShareData

  20. class TaskManager(object):
  21.     #--该类为单例模式
  22.     #__metaclass__ = Singleton
  23.     def __init__(self,logger = None):
  24.         self.logger = logger
  25.         #self.logger.info('init TaskManager')
  26.         self.evt_dispatch = eventDispatch.EventDispatch() #--事件分发
  27.         #self.logger.info('evt_dispatch ok')
  28.         self.share_data = ShareData()   #--全局的共享数据
  29.         #self.logger.info('share_data ok')
  30.         for chan_name in config.CHANNAL_LIST:   #--创建-全局数据频道
  31.             self.share_data.add_channal(chan_name)
  32.             #self.logger.info('channal ok')

  33.     def loop(self):
  34.         self.evt_dispatch.add_all()
  35.         #self.logger.info('self.evt_dispatch.add_all()')
  36.         self.evt_dispatch.dispatch()
  37.         #self.logger.info('self.evt_dispatch.dispatch()')

  38.     def stop(self):
  39.         print('TaskManager stop')
  40.         #self.logger.info("TaskManager stop")
  41.         self.evt_dispatch.destroy()



  42. if __name__=='__main__':
  43.     tm = TaskManager()
  44.     tm.loop()
  45.     time.sleep(20)
  46.     print 'after 10s...'
  47.     tm.stop()

复制代码
EventDispatch类:
  1. #coding=gb2312
  2. #-------------------------------------------------------------------------------
  3. # Name:        模块1
  4. # Purpose:
  5. #
  6. # Author:      Administrator
  7. #
  8. # Created:     02/03/2012
  9. # Copyright:   (c) Administrator 2012
  10. # Licence:     <your licence>
  11. #-------------------------------------------------------------------------------
  12. #!/usr/bin/env python
  13. import time
  14. import glob
  15. import os

  16. from common.util import import_all_module,get_logger
  17. from common.singleton import Singleton #--单例模式

  18. class EventDispatch(object):
  19.      #--该类为单例模式
  20.     __metaclass__ = Singleton
  21.     event_queue = []    #--消息队列
  22.     event_num = 0   #--队列中消息的数量
  23.     tick_event_num = 0  #--队列中,等待触发的消息数量

  24.     def __init__(self,evts = None):
  25.         if isinstance(evts,list):
  26.             self.event_queue = evts
  27.         self.event_num = len(self.event_queue)
  28.         self.running_event = []

  29.     def add_event(self,evt):
  30.         self.event_queue.append(evt)

  31.     def add_all(self):
  32.         import inspect
  33.         #logger = get_logger('EventDispatch_add_all')
  34.         #--获得当前文件和当前文件所在的目录
  35.         this_file = inspect.getfile(inspect.currentframe())
  36.         this_dir = os.path.abspath(os.path.dirname(this_file))
  37.         path = os.path.join(this_dir,'customEvent')
  38.         #logger.info(path)
  39.         class_list = import_all_module(path,'event.customEvent','evt_*.py')
  40.         #logger.info(class_list)
  41.         if class_list:
  42.             self.event_queue = class_list
  43.         #logger.info('EventDispatch_add_all end')

  44.     def dispatch(self,sleep_time = 5):
  45.         time.sleep(sleep_time) #--默认5秒后,才开始触发事件
  46.         logger = get_logger('dispatch_dispatch')
  47.         for evt in self.event_queue:
  48.             e = evt()
  49.             self.running_event.append(e)
  50.             #logger.info('before fire_event:%s'%(e))
  51.             e.fire_event()
  52.             logger.info('after fire_event:%s'%(e))
  53.             logger.info('running_event num is %s,event_queue num is %s'%(len(self.running_event),len(self.event_queue)))

  54.     def dispatch_ex(self,evt):
  55.         self.event_queue.append(evt)
  56.         e = evt()
  57.         self.running_event.append(e)
  58.         e.fire_event()

  59.     def get_event(self,event_name):
  60.         '''
  61.         获取一个事件对象,参数为事件名字
  62.         '''
  63.         for evt in self.running_event:
  64.             if evt._EVENT_NAME == event_name:
  65.                 return evt

  66.     def wake_up(self,event_name):
  67.         '''
  68.         唤醒事件,参数为事件名字
  69.         '''
  70.         evt = self.get_event(event_name)
  71.         if evt and evt.status == evt._SLEEPING:
  72.                 logger = get_logger('dispatch_wake_up')
  73.                 logger.info('dispatch instance is %s, evt is %s,wake_up:%s'%(self,evt,evt._EVENT_NAME))
  74.                 evt.switch(evt._WAKEUP)


  75.     def destroy(self):
  76.         for evt in self.running_event:
  77.             evt.abort()
  78.         self.running_event = []
  79.         self.event_queue = []

  80. if __name__=='__main__':
  81.     evt = EventDispatch()
  82.     evt.add_all()

复制代码
事件基类:
  1. #coding=gb2312
  2. #-------------------------------------------------------------------------------
  3. # Name:        事件基类
  4. # Purpose:
  5. #
  6. # Author:      Weigun
  7. #
  8. # Created:     08/23/2013
  9. # Copyright:   (c) Administrator 2012
  10. # Licence:     <your licence>
  11. #-------------------------------------------------------------------------------
  12. #!/usr/bin/env python
  13. import os
  14. import sys
  15. import time

  16. from common.util import get_logger
  17. from common.timer import Timer
  18. class EventBase(object):
  19.     _EVENT_NAME = '' #--事件名字
  20.     _IDLE = 0   #--事件的3个状态
  21.     _WOKING = 1
  22.     _FINISH = 2
  23.     _SLEEPING = -1
  24.     _WAKEUP = -2
  25.     _KEEP_ALIVE = False

  26.     def __init__(self,*args,**kwargs):
  27.         self.tick = 0  #--repeat型的事件,执行间隔,默认是0秒,如果为0则表示一次性事件
  28.         self.status= self._IDLE
  29.         self.sleep_time = 1 #--默认随眠5秒
  30.         self._EVENT_NAME = self.__class__.__name__

  31.     def keep_alive(self,alive = None):
  32.         '''
  33.         设置事件是否不销毁
  34.         para: alive = None then return self._KEEP_ALIVE,otherwise setattr self._KEEP_ALIVE = alive
  35.         '''
  36.         if alive:
  37.             self._KEEP_ALIVE = alive
  38.         else:
  39.             return self._KEEP_ALIVE

  40.     def switch(self,staus):
  41.         '''
  42.         切换事件的状态
  43.         '''
  44.         self.status = staus

  45.     def fire_event(self):
  46.         '''
  47.         激活事件
  48.         '''
  49.         logger = get_logger('fire_event')
  50.         self.status = self._WOKING
  51.         #logger.info('it woking')
  52.         try:
  53.             #logger.info('timer type:%s,%s'%(Timer,type(Timer)))
  54.             self.task = Timer(self.tick,self.__do)
  55.             #logger.info('timer ready:%s'%(self.task))
  56.             self.task.start()
  57.             logger.info('timer started:%s'%(self.task))
  58.         except:
  59.             pass
  60.             #info=sys.exc_info()
  61.             #logger.info('exception:%s,%s,%s'%(info[0],info[1],info[2]))

  62.     def __do(self):
  63.         #--注意stop的时候该线程是否会停掉
  64.         self.do()
  65.         if self.keep_alive():
  66.             logger = get_logger('keepAlive')
  67.             self.switch(self._SLEEPING)
  68.             logger.info('switch to %s'%(self._SLEEPING))
  69.         while(self.keep_alive()):
  70.             if self.status == self._SLEEPING:
  71.                 time.sleep(self.sleep_time)
  72.                 #logger.info('after sleep now continue')
  73.                 continue
  74.             logger.info('now,wake up,staus is %s'%(self.status))
  75.             self.do()
  76.             self.switch(self._SLEEPING)
  77.             logger.info('switch to %s'%(self._SLEEPING))




  78.     def do(self):
  79.         '''
  80.         事件的逻辑函数,逻辑代码都往这里填
  81.         '''
  82.         pass

  83.     def abort(self):
  84.         '''
  85.         强制中断事件
  86.         '''
  87.         self.task.stop()

  88. if __name__=='__main__':
  89.     evt = EventBase()


复制代码
事件类:
  1. #coding=gb2312
  2. #-------------------------------------------------------------------------------
  3. # Name:        模块1
  4. # Purpose:
  5. #
  6. # Author:      Administrator
  7. #
  8. # Created:     02/03/2012
  9. # Copyright:   (c) Administrator 2012
  10. # Licence:     <your licence>
  11. #-------------------------------------------------------------------------------
  12. #!/usr/bin/env python
  13. import time

  14. from event import EventBase
  15. from common.util import get_logger
  16. from event.eventDispatch import EventDispatch
  17. class evt_myevt2(EventBase):
  18.     def __init__(self,*args,**kwargs):
  19.         super(evt_myevt2,self).__init__(*args,**kwargs)
  20.         self.tick = 5
  21.         self.loggr = get_logger('evt_myevt2')

  22.     def do(self):
  23.         print 'i am %s,running~~'%(self._EVENT_NAME)
  24.         self.status = self._IDLE
  25.         print 'now i am ',self.status
  26.         self.loggr.info('i am evt_myevt2,good for running')
  27.         time.sleep(10)
  28.         evtmgr = EventDispatch()
  29.         print '--------now i wake up evt_ConfigChk'
  30.         self.loggr.info('--------now i wake up evt_ConfigChk')
  31.         evtmgr.wake_up('evt_ConfigChk')






  32. if __name__=='__main__':
  33.     evt = EventBase()


复制代码
timer类:
  1. #coding=gb2312
  2. #-------------------------------------------------------------------------------
  3. # Name:        模块1
  4. # Purpose:
  5. #
  6. # Author:      Administrator
  7. #
  8. # Created:     02/03/2012
  9. # Copyright:   (c) Administrator 2012
  10. # Licence:     <your licence>
  11. #-------------------------------------------------------------------------------
  12. #!/usr/bin/env python
  13. import threading
  14. import time
  15. import sys

  16. from common.util import get_logger
  17. class SimpleTimer(threading.Thread):
  18.         """
  19.         very simple but useless timer.
  20.         """
  21.         def __init__(self, seconds):
  22.                 self.runTime = seconds
  23.                 threading.Thread.__init__(self)
  24.         def run(self):
  25.                 time.sleep(self.runTime)
  26.                 print "Buzzzz!! Time's up!"

  27. class Timer(object):
  28.     def __init__(self, interval, function, args=[], kwargs={}):
  29.         self.logger = get_logger('Timer')
  30.         self.interval = interval
  31.         self.function = function
  32.         self.args = args
  33.         self.kwargs = kwargs

  34.     def start(self,interval = 5):
  35.         self.stop()
  36.         import threading
  37.         self._timer = threading.Timer(interval, self._run)
  38.         self._timer.setDaemon(True)
  39.         self._timer.start()
  40.         self.logger.info('timer instance <%s> started:%s'%(self._timer,interval))

  41.     def restart(self,interval = None):
  42.         self.start(interval or self.interval)

  43.     def stop(self):
  44.         if self.__dict__.has_key("_timer"):
  45.             print 'timer:',self._timer, ' stop'
  46.             self._timer.cancel()
  47.             self.logger.info('timer instance <%s> cancel ok'%(self._timer))
  48.             del self._timer


  49.     def _run(self):
  50.         try:
  51.             self.function(*self.args, **self.kwargs)
  52.         except:
  53.             print 'timer got exception'
  54.             exc_info = sys.exc_info()
  55.             self.logger.info('timer_run got exception:%s,%s'%(exc_info[0],exc_info[1]))
  56.             self.stop()
  57.         if self.interval and self.interval != 0:
  58.             self.restart()
  59.         else:
  60.             self.stop()


  61. if __name__=='__main__':
  62.     tm = TaskManager()
  63.     tm.loop()
  64.     tm.stop()

复制代码
get_logger方法:
  1. def get_logger(log_name,log_path = None):
  2.     logger = logging.getLogger('[%s]'%(log_name))
  3.     if log_path:
  4.         if os.path.isdir(log_path) and os.path.exists(log_path):
  5.             dirpath = log_path
  6.     else:
  7.         dirpath = config.LOG_DIR
  8.     log_name = log_name + '.log'
  9.     handler = logging.FileHandler(os.path.join(dirpath, log_name))
  10.     formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
  11.     handler.setFormatter(formatter)
  12.     logger.addHandler(handler)
  13.     logger.setLevel(logging.INFO)
  14.     return logger
复制代码
附上相关的log:
dispatch_dispatch:
  1. 2013-08-27 01:41:43,144 [dispatch_dispatch] INFO     after fire_event:<event.customEvent.evt_ConfigChk.evt_ConfigChk object at 0x02688E50>
  2. 2013-08-27 01:41:43,144 [dispatch_dispatch] INFO     running_event num is 1,event_queue num is 3
  3. 2013-08-27 01:41:43,148 [dispatch_dispatch] INFO     after fire_event:<event.customEvent.evt_myevt2.evt_myevt2 object at 0x0268E0F0>
  4. 2013-08-27 01:41:43,148 [dispatch_dispatch] INFO     running_event num is 2,event_queue num is 3
  5. 2013-08-27 01:41:43,151 [dispatch_dispatch] INFO     after fire_event:<event.customEvent.evt_Templet.evt_Templet object at 0x0268E390>
  6. 2013-08-27 01:41:43,151 [dispatch_dispatch] INFO     running_event num is 3,event_queue num is 3
复制代码
dispatch_wake_up:
  1. 2013-08-27 01:41:58,151 [dispatch_wake_up] INFO     dispatch instance is <event.eventDispatch.EventDispatch object at 0x0267FC90>, evt is <event.customEvent.evt_ConfigChk.evt_ConfigChk object at 0x02688E50>,wake_up:evt_ConfigChk
复制代码
fire_event:
  1. 2013-08-27 01:41:43,144 [fire_event] INFO     timer started:<common.timer.Timer object at 0x02688EF0>
  2. 2013-08-27 01:41:43,148 [fire_event] INFO     timer started:<common.timer.Timer object at 0x0268E210>          #--为什么有相同的timer
  3. 2013-08-27 01:41:43,148 [fire_event] INFO     timer started:<common.timer.Timer object at 0x0268E210>        #--为什么有相同的timer       
  4. 2013-08-27 01:41:43,150 [fire_event] INFO     timer started:<common.timer.Timer object at 0x0268E410>
  5. 2013-08-27 01:41:43,150 [fire_event] INFO     timer started:<common.timer.Timer object at 0x0268E410>
  6. 2013-08-27 01:41:43,150 [fire_event] INFO     timer started:<common.timer.Timer object at 0x0268E410>
复制代码

论坛徽章:
0
2 [报告]
发表于 2013-08-27 13:48 |只看该作者
现在我初步怀疑是logger的问题····每new一个timer就会多写一次···因为我对比过print与logg的记录···print的打印是正确的·····求科普··

论坛徽章:
0
3 [报告]
发表于 2013-08-27 20:36 |只看该作者
本帖最后由 wfnh 于 2013-08-27 22:59 编辑

回复 2# wfnh

其实也不能说是logger的问题···应该是我的写法的问题··
我的解决办法是将logger = get_logger('fire_event')这句···放在模块开始,类定义之前,作为该模块的 一个全局变量,就可以了,这里不应该放在do或者需要new线程(timer)的类里边的,断点跟了一下,跟到logging模块里边去,发现‘evt_myevt2’这个log的实例下的有很多的handler,每一个handler都会写一次log的,这里有多少个就会写多少次,故出现上述情况。

ps:logging里边没有时间细看,不知道哪里与这个有关系·,难道通过与tid绑定!?··有了解的童鞋,求科普

ps1:又或者是我每次调get_logger方法,里边都会addHandler导致···有时间再看看
   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP