#!/usr/bin/python
# -*- coding: utf-8 -*
# #############################################################################
#
# Copyright (c) 2014 Baidu.com, Inc. All Rights Reserved
#
# #############################################################################
"""
:author:
Guannan Ma maguannan @mythmgn
:create_date:
2014
:last_date:
2014
:descrition:
decorators related module
"""
from datetime import datetime as datetime_in
import platform
import time
import threading
from functools import wraps
import cup
__all__ = ['Singleton', 'needlinux', 'TraceUsedTime']
[docs]class Singleton(object): # pylint: disable=R0903
"""
Singleton你的类.
用法如下::
import cup
@cup.decorator.Singleton
class YourClass(object):
def __init__(self):
pass
"""
def __init__(self, cls):
self.__instance = None
self.__cls = cls
self._lock = threading.Lock()
def __call__(self, *args, **kwargs):
self._lock.acquire()
if self.__instance is None:
self.__instance = self.__cls(*args, **kwargs)
self._lock.release()
return self.__instance
def py_versioncheck(function, version):
"""
:platform:
any platform + any functions in python
:param version:
Version of python which should be <= version of the OS.
*E.g. version=('2', '7', '0')*
Python version should >= version.
"""
ind = 0
py_version = platform.python_version_tuple()
for i in py_version:
if int(version(ind)) < int(i):
raise cup.err.DecoratorException(
'Python version check failed. You expect version >= %s,'
'but python-version on this machine:%s' %
(version, py_version)
)
ind += 1
return function
[docs]def needlinux(function):
"""
:platform: Linux
只支持linux的python修饰符, 用来表明这个函数只能运行在linux系统上.
如果函数运行在非linux平台, raise cup.err.DecoratorException
用法如下::
import cup
@cup.decorator.needlinux
def your_func():
pass
"""
if platform.system() != 'Linux':
raise cup.err.DecoratorException(
'The system is not linux.'
'This functionality only supported in linux'
)
return function
# pylint:disable=R0903
[docs]class TraceUsedTime(object):
"""
追踪函数的耗时情况
如果init过cup.log.init_comlog, 会打印到log文件。
example:
::
import time
from cup import decorators
@decorators.TraceUsedTime(True)
def test():
print 'test'
time.sleep(4)
# trace something with context. E.g. event_id
def _test_trace_time_map(sleep_time):
print "ready to work"
time.sleep(sleep_time)
traced_test_trace_time_map = decorators.TraceUsedTime(
b_print_stdout=False,
enter_msg='event_id: 0x12345',
leave_msg='event_id: 0x12345'
)(_test_trace_time_map)
traced_test_trace_time_map(sleep_time=5)
"""
def __init__(self, b_print_stdout=False, enter_msg='', leave_msg=''):
"""
:param b_print_stdout:
自动打印到由cup.log.init_comlog设置的logfile中,
如果init_comlog未被调用和初始化,则不会打印。
如果b_print_stdout=True, 则会同时打印时间追踪日志到stdout.
:param enter_msg:
会在函数进入时期也同步打印的msg
:param leave_msg:
会在函数离开时期同步打印的msg
建议如果不使用cup.log.init_comlog打日志的话,则b_print_stdout=True
"""
self._b_print_stdout = b_print_stdout
self._enter_msg = enter_msg
self._leave_msg = leave_msg
def __call__(self, function):
@wraps(function)
def _wrapper_log(*args, **kwargs):
now = time.time()
if self._b_print_stdout:
print '**enter func:%s,time:%s, msg:%s' % (
function, datetime_in.now(), self._enter_msg
)
cup.log.info(
'**enter func:%s, msg:%s' % (function, self._enter_msg)
)
function(*args, **kwargs)
then = time.time()
used_time = then - now
cup.log.info(
'**leave func:%s, used_time:%f, msg:%s' % (
function, used_time, self._enter_msg
)
)
if self._b_print_stdout:
print '**leave func:%s, time:%s, used_time:%f, msg:%s' % (
function, datetime_in.now(), used_time, self._leave_msg
)
return _wrapper_log
# Things below for unittest
@TraceUsedTime(False)
def _test_trace_time():
print 'now', time.time(), datetime_in.now()
time.sleep(3)
print 'then', time.time(), datetime_in.now()
@TraceUsedTime(True)
def _test_trace_time_log():
print 'now', time.time(), datetime_in.now()
time.sleep(3)
print 'then', time.time(), datetime_in.now()
def _test_trace_time_map(sleep_time):
print "ready to work"
time.sleep(sleep_time)
def _test():
cup.log.init_comlog(
'test', cup.log.DEBUG, './test.log',
cup.log.ROTATION, 102400000, False
)
_test_trace_time()
_test_trace_time_log()
func = TraceUsedTime(
b_print_stdout=False,
enter_msg='event_id: 0x12345',
leave_msg='event_id: 0x12345'
)(_test_trace_time_map)
func(sleep_time=5)
if __name__ == '__main__':
_test()
# vi:set tw=0 ts=4 sw=4 nowrap fdm=indent