使用线程锁来实现一个简单写日志到数据库的功能,通过threading锁来实现线程安全,代码如下:
#-*-utf-8-*-
import logging, datetime, time
from multiprocessing import Queue, Process
import cx_Oracle
import threading
class LogInfo(object):
def __init__(self, logTime, scriptName, logType, message):
self.logTime = logTime
self.scriptName = scriptName
self.logType = logType
self.message = message
def __str__(self):
return self.scriptName + " " + self.logType + " " + str(self.message)
def insertLog(LogInfo):
with cx_Oracle.connect("system/1234@orcl") as conn:
cursor = conn.cursor()
sqlStr = "insert into SYSTEM.etl_logs values (to_timestamp('%s', 'YYYY-MM-DD HH24:MI:SS.FF'), '%s', '%s', '%s')"
cursor.execute(sqlStr % (LogInfo.logTime, LogInfo.scriptName, LogInfo.logType, LogInfo.message))
conn.commit()
class Log2DB(object):
instance = None
def __new__(cls):
if cls.instance:
return cls.instance
cls.instance = object.__new__(cls)
cls.instance.queue = Queue()
cls.instance._lock = threading.RLock()
return cls.instance
def flag(self, text):
time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M%S.%f')
log = LogInfo(time, 'a', 'flag', text)
self._insert(log)
def info(self, text):
time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M%S.%f')
log = LogInfo(time, 'b', 'info', text)
self._insert(log)
def error(self, text):
time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M%S.%f')
log = LogInfo(time, 'c', 'error', text)
self._insert(log)
def warn(self, text):
time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M%S.%f')
log = LogInfo(time, 'd', 'warn', text)
self._insert(log)
def _insert(self, log):
self._lock.acquire()
try:
print(log)
insertLog(log)
except Exception as e:
print(str(e.args))
finally:
self._lock.release()
log2db = Log2DB()
def a():
for i in range(1000):
log2db.flag("a"+str(i))
def b():
for i in range(1000):
log2db.info(i)
if __name__ == '__main__':
ap = Process(target=a)
ap.start()
bp = Process(target=b)
bp.start()
ap.join()
bp.join()
不过效率也就一般了,基本上3秒才能写入一条记录,后来加了时间打印了一下发现是写DB的过程太耗时导致,需要考虑批量提交比较好,下一篇准备实现一个无阻塞的日志入库的程序。