python多线程生成excel一些感悟吧...

Excel批量生成优化
本文分享了一种使用Python的多线程、协程和进程池来提高Excel报表生成效率的方法,解决了因IO交互导致的线程卡死问题,大幅提升了生成速度。
最近,做了很多个报表,一开始并没有考虑到效率的问题,只是实现了excel的导出,后来慢慢做出现好多问题。
1、每一个excel 的sheet很多,大概四五十个,跑完一个excel得花四十多分钟,甚至一个小时。。。有时候甚至线程直接卡死了不动了。可能是io的交互太长了,也不知道撒原因。
2、每一类型的excel至少也得需要出30多个吧,考虑到进程池用多进程去跑,但是发现多进程消耗太大,机器也就4核的,我至少也得开十个进程,机器扛不住,可能也还是IO的交互时间长,进程也会卡死,所以放弃了。
3、为了解决进程池的开销太大,和进程卡死的问题,我改成了线程池,每一个类型的excel开启十个线程去跑,但是python的线程由于GIL全局锁的原因,实际上每次还是一个线程再跑,而且对每一个excel来说,很多个sheet需要生成,同一个线程中IO交互也非常频繁,而且还是会存在线程卡死的情况,效率也不行。
4、为了解决进程池的开销问题,和线程池中的io交互过长,会导致线程卡死,IO交互的时候线程会暂停等待IO交互而白白浪费时间。最终,goole、百度,python的协程,简直是神器,IO交互的时候,线程不会等待,而是会执行其他的协程。
5、因为我的是flask应用,需要向其他应用提供生成excel的接口,最终我的解决方案是,在每一个web请求中,创建进程池异步调用,并创建线程池(为了跑多个excel),每个线程开启多个协程任务(生成每个excel中的sheet)。大大提高了excel的生成效率,而且,线程也没与出现卡死的情况。下面是,threadpool 和 协程的基本使用:

1、每一个线程里面会有多个协程对象。
2、协程的运行是由顺序的,只是在IO交互的时候,不用等待IO交互完成。
3、多线程中使用协程的时候必须新建loop对象。

import threadpool
import asyncio
import time


async def do_work_one(name):
    """
    定义一个协程对象
    :return:
    """
    time.sleep(4)
    print(name, 'do_work_one')


async def do_work_two(name):
    """
    定义一个协程对象
    :return:
    """
    time.sleep(2)
    print(name, 'do_work_two')


def task_do_work(name):
    """
    1、每一个线程里面会有多个协程对象
    2、协程的运行是由顺序的,只是在IO交互的时候,不用等待IO交互完成
    3、多线程中使用协程的时候必须新建loop对象
    :return:
    """
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    coroutine1 = do_work_one(name)
    coroutine2 = do_work_two(name)

    tasks = [asyncio.ensure_future(coroutine1), asyncio.ensure_future(coroutine2)]
    loop.run_until_complete(asyncio.wait(tasks))
    return 'success'


def call_back(param, result):
    print('回调', param, result)


if __name__ == '__main__':
    jobs = []
    pool = threadpool.ThreadPool(2)
    work_requests = []
    for i in range(2):
        work_requests.append(threadpool.WorkRequest(task_do_work, args=('线程-{0}'.format(i), ), callback=call_back, exc_callback=call_back))
    [pool.putRequest(req) for req in work_requests]
    pool.wait()
    print('end')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永不止步——

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值