美文网首页
python使用装饰器将函数的print打印写入文件

python使用装饰器将函数的print打印写入文件

作者: 托贝多尔 | 来源:发表于2020-09-19 23:30 被阅读0次

需求点:设计个装饰器将print输出保存到日志中

import os
import sys
import threading
import time
from functools import wraps

#指定日志路径
logpath = os.path.join(os.path.dirname(__file__), 'log.txt')
def save_print_to_log(act_def):
    def wrapper(*args, **kwargs):
        #将打印临时保存
        sys.stdout = open('temp.txt', 'w', encoding='utf-8')
        act_def(*args, **kwargs)
        sys.stdout.close()
        with open('temp.txt', 'r', encoding='utf-8')as tmp:
            with open(logpath, 'a+', encoding='utf-8')as fp:
                #写入日志的格式
                fp.write('[{}][{}]:{}'.format(time.strftime('%Y-%m-%d %X'), act_def.__name__,tmp.read()))
    return wrapper


@save_print_to_log
def get_log():
    print('这个一个日志打印')

四次执行结果:
[2020-09-19 23:18:48]这个一个日志打印
[2020-09-19 23:19:01]这个一个日志打印
[2020-09-19 23:22:14]这个一个日志打印
[2020-09-19 23:22:27]这个一个日志打印
小结:
这个装饰器对多线程支持不友好,以下是我添加线程锁之后的代码,貌似还不理想,自己感觉是线程用的不合适,但还没想到好的解决办法,请大佬们看到的话分享些建议,不胜感激!

import os
import sys
import threading
import time
from functools import wraps

logpath = os.path.join(os.path.dirname(__file__), 'log.txt')


def count_time(act_def):
    @wraps(act_def)
    def _count():
        start_time = time.time()
        with open(logpath, 'a', encoding='utf-8')as pf:
            pf.write('开始...\n')
        act_def()
        end_time = time.time()
        with open(logpath, 'a', encoding='utf-8')as pf:
            pf.write('结束!\n耗时:%s' % (end_time - start_time))

    return _count


going = threading.Lock()


def save_print_to_log(act_def):
    def wrapper(*args, **kwargs):
        global going
        with going:
            sys.stdout = open('temp.txt', 'w+', encoding='utf-8')
            act_def(*args, **kwargs)
            sys.stdout.close()

            with open('temp.txt', 'r', encoding='utf-8')as tmp:
                with open(logpath, 'a', encoding='utf-8')as fp:
                    fp.write('[{}][{}]:{}'.format(time.strftime('%Y-%m-%d %X'), act_def.__name__, tmp.read()))

    return wrapper


@save_print_to_log
def get_log1():
    print('这是函数1日志')


@save_print_to_log
def get_log2():
    print('这是函数2日志')


@count_time
def try_test1():
    cout = 0
    for i in range(0, 5):
        cout += 1
        time.sleep(0.5)  # 线程启动太快会乱,应该是文件来不及关闭导致的
        t = threading.Thread(target=get_log1, )
        t2 = threading.Thread(target=get_log2, )
        t.setDaemon(True)
        t2.setDaemon(True)
        t.start()
        t2.start()

    with open(logpath, 'a', encoding='utf-8')as fp:
        fp.write(str(cout)+'次执行\n')


try_test1()


测试结果:
开始...
[2020-09-20 17:06:46][get_log1]:这是函数1日志
[2020-09-20 17:06:46][get_log2]:这是函数2日志
[2020-09-20 17:06:46][get_log1]:这是函数1日志
[2020-09-20 17:06:46][get_log2]:这是函数2日志
[2020-09-20 17:06:47][get_log1]:这是函数1日志
[2020-09-20 17:06:47][get_log2]:这是函数2日志
[2020-09-20 17:06:47][get_log1]:这是函数1日志
[2020-09-20 17:06:47][get_log2]:这是函数2日志
5次执行
结束!
耗时:2.506901264190674

总结:
修改后的代码执行结果永远差两次记录,这个很让我头疼,没找到问题原因在哪儿。。。

相关文章

网友评论

      本文标题:python使用装饰器将函数的print打印写入文件

      本文链接:https://www.haomeiwen.com/subject/gutuyktx.html