Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5096032
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类: Python/Ruby

2015-10-11 10:10:37

twisted日志系统提供了按照日期自动创建日志文件的功能, 不需要启动reactor也可以使用

启动日志示例代码:

  1. outpath = '/Users/.../log'
  2. outname = 'server.log'
  3. if not os.path.exists(outpath) :
  4.     os.mkdir(outpath)
  5. log.FileLogObserver.timeFormat = '%m-%d %H:%M:%S'
  6. log_file = logfile.DailyLogFile(outname, outpath)
  7. log.startLogging(log_file)

log系统初始化(twisted/python/log.py):

  1. logfile = StdioOnnaStick(0, getattr(sys.stdout, "encoding", None)) # 封装sys.stdout
  2. logerr = StdioOnnaStick(1, getattr(sys.stderr, "encoding", None)) # 封装sys.stderr
如何启动日志系统:

  1. def startLogging(file, *a, **kw):
  2.   # 创建观察者,有日志或者说stdout.write操作的时候通知每个observer, file就是DailyLogFile
  3.   flo = FileLogObserver(file)
  4.   startLoggingWithObserver(flo.emit, *a, **kw) # 开始启动观察者

  5. def startLoggingWithObserver(observer, setStdout=1):
  6.   addObserver(observer) # observe就是flo.emit函数
  7.   msg("Log opened.")
  8.   if setStdout:
  9.       sys.stdout = logfile # 将正常的print打印重定向到logfile对象
  10.       sys.stderr = logerr

从调用print语句开始打印分析日志打印的代码流程:


  1. # print -> stdout.write -> logfile.write

  2. # 所以看下logfile所对应的StdioOnnaStick类中write方法:
  3.   def write(self, data): # 如何到达这步:print -> stdout.write -> logfile.write
  4.       ...
  5.       self.buf = d[-1]
  6.       messages = d[0:-1]
  7.       for message in messages:
  8.           msg(message, printed=1, isError=self.isError) # 调用theLogPublisher.msg

  9. # LogPublisher的msg方法:
  10.   def msg(self, *message, **kw):
  11.     actualEventDict = (context.get(ILogContext) or {}).copy()
  12.     actualEventDict.update(kw)
  13.     actualEventDict['message'] = message
  14.     actualEventDict['time'] = time.time()
  15.     for i in range(len(self.observers) - 1, -1, -1): # 遍历注册的日志观察者
  16.         try:
  17.             # 调用observer函数,就是FileLogObserver.emit()
  18.             self.observers[i](actualEventDict)
  19.     ...

  20. # FileLogObserver.emit方法:

  21.   def emit(self, eventDict):
  22.     text = textFromEventDict(eventDict)
  23.     if text is None:
  24.         return

  25.     timeStr = self.formatTime(eventDict['time'])
  26.     fmtDict = {'system': eventDict['system'], 'text': text.replace("\n", "\n\t")}
  27.     msgStr = _safeFormat("[%(system)s] %(text)s\n", fmtDict)

  28.     # 调用最开始FileLogObserver()传入的DailyLogFile.write
  29.     util.untilConcludes(self.write, timeStr + " " + msgStr)
  30.     util.untilConcludes(self.flush) #
  31.  
  32. # DailyLogFile.write:

  33.   def write(self, data):
  34.     """Write some data to the log file"""
  35.     BaseLogFile.write(self, data)
  36.     self.lastDate = max(self.lastDate, self.toDate())

  37. # BaseLogFile.write:

  38.   def write(self, data):
  39.     if self.shouldRotate(): # 根据日期判断是否需要另起一个log文件:if self.toDate() > self.lastDate
  40.         self.flush()
  41.         self.rotate() # 调用DailyLogFile.rotate()方法新建log文件
  42.     self._file.write(data) # 终于开始写文件了

  43. # DailyLogFile.rotate:

  44.   def rotate(self):
  45.       if not (os.access(self.directory, os.W_OK) and os.access(self.path, os.W_OK)):
  46.           return
  47.       newpath = "%s.%s" % (self.path, self.suffix(self.lastDate))
  48.       if os.path.exists(newpath):
  49.           return
  50.       self._file.close()
  51.       os.rename(self.path, newpath) # 将当前的log文件重命名为带日期的历史log文件
  52.       self._openFile() # 以self.path为路径打开一个新文件准备写入

原文链接
阅读(2033) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~