AttributeError: Can't pickle local object 解决办法

今天意外的发现了python装饰器和多进程之间的一个小坑,起初简单写了一个装饰器,用来给程序计时,自测了下没有什么问题

def times_used(*dargs):
    def time_(f):
        def count_time(*args, **kw):
            start = datetime.datetime.now()
            print("【{}】开始时间为:{}".format(dargs, start.strftime('%Y-%m-%d %H:%M:%S')))
            f_res = f(*args, **kw)
            end = datetime.datetime.now()
            interval = (end - start).seconds
            times = datetime.timedelta(seconds=interval)
            print("【{}】结束时间:{},耗时{}".format(dargs, end.strftime('%Y-%m-%d %H:%M:%S'), times))
            return f_res
        return count_time
    return time_


@times_used('哈哈')
def haha(name):
    time.sleep(1)
    print("hello {}".format(name))


if __name__ == '__main__':
    haha("world")

 

输出也正常:

AttributeError: Can't pickle local object 解决办法_第1张图片

然后就准备把它加入我遍历文件夹模块。但是加入到模块里以后开始报错:

 这里我查了很久,最后发现了问题是由于python的多进程导致的,多进程获取返回值是需要序列化的,但是装饰器是无法序列化的,所以报错。查阅资料找到解决办法为:functools.wraps,它可以解除这种束缚,从而变的可序列化。代码如下:

def times_used(*dargs):
    def time_(f):
        @wraps(f)
        def count_time(*args, **kw):
            start = datetime.datetime.now()
            print("【{}】开始时间为:{}".format(dargs, start.strftime('%Y-%m-%d %H:%M:%S')))
            f_res = f(*args, **kw)
            end = datetime.datetime.now()
            interval = (end - start).seconds
            times = datetime.timedelta(seconds=interval)
            print("【{}】结束时间:{},耗时{}".format(dargs, end.strftime('%Y-%m-%d %H:%M:%S'), times))
            return f_res
        return count_time
    return time_

这样在运行就不会再报错了。

参考资料:http://gael-varoquaux.info/programming/decoration-in-python-done-right-decorating-and-pickling.html

你可能感兴趣的:(python)