使用python多进程批量转换word为PDF

前几天收到客户3万多个word文件要印刷,为了能拼版,需要先将文件批量转化为PDF,人工肯定是不行,需要写一个自动转化脚本。
原理很简单,就是通过Word.Application接口打开word文件,另存为PDF。我实验一个20页的A4黑白文件转化需要20秒,效率低了一些,所以加入多进程加快速度。
首先,docx2pdf函数负责将docx格式文件转化为PDF:

def docx2pdf(input_file):
    """docx转pdf"""
    word = Dispatch('Word.Application')
    doc = word.Documents.Open(input_file)
    doc.SaveAs(input_file.replace(".docx", ".pdf"), FileFormat=17)
    doc.Close()
    word.Quit()

源文件中可能混杂有doc和docx两种文件格式,所以有必要先将doc转化为docx:

def doc2docx(doc_name,docx_name):
    """doc转docx"""
    try:
        # 首先将doc转换成docx
        word = client.Dispatch("Word.Application")
        doc = word.Documents.Open(doc_name)
        #使用参数16表示将doc转换成docx
        doc.SaveAs(docx_name,16)
        doc.Close()
        word.Quit()
    except:
        pass

遍历文件夹docx文件,由函数find_docs负责:

def find_docs(path):
    """获取文件夹下所有docx文件列表"""
    docs= []
    for root, dirs, filenames in walk(path):
        for file in filenames:
            if file.endswith(".doc"):
                doc2docx(f"{root}\\{file}",f"{root}\\{file}x")
                docs.append(f"{root}\\{file}x")
            elif file.endswith(".docx"):
                docs.append(f"{root}\\{file}")
    docs = list(set(docs))  #去重
    # print(docs)
    return docs

将这3块代码合并就可以实现多word转PDF了。下面是加入多进程,先看看CPU数量:

    from multiprocessing import cpu_count
    print("cpu个数:",cpu_count())  #获取CPU个数

多进程要在主函数中完成,为了减少耦合,专门为多进程加了一个worker函数,来调用docx2pdf,实际上可以让多进程直接调用docx2pdf。我电脑是8核的,开了5个进程:

def worker(input_file):
    print("{}  开始转化...\n".format(input_file))
    docx2pdf(input_file)
    print("{}  【转化完成】".format(input_file))

def main():  #多进程必须放在主程序中设置
    directory = r"C:\Users\31209\Desktop\新建文件夹"
    from multiprocessing import cpu_count
    print("cpu个数:",cpu_count())  #获取CPU个数
    ps = Pool(5) #设置线程池
    docs = find_docs(directory)
    if docs !=[]:
        print("主进程开始执行:")
        for i in docs:
            # ps.apply(worker,args=(i,))          # 同步执行
            ps.apply_async(worker,args=(i,))  # 异步执行
        ps.close() # 关闭进程池,停止接受其它进程
        ps.join()# 阻塞进程
        print("主进程终止!")

完整代码:

from win32com.client import Dispatch
from os import walk
import os,time

from win32com import client
def doc2docx(doc_name,docx_name):
    """doc转docx"""
    try:
        # 首先将doc转换成docx
        word = client.Dispatch("Word.Application")
        doc = word.Documents.Open(doc_name)
        #使用参数16表示将doc转换成docx
        doc.SaveAs(docx_name,16)
        doc.Close()
        word.Quit()
    except:
        pass

def docx2pdf(input_file):
    """docx转pdf"""
    word = Dispatch('Word.Application')
    doc = word.Documents.Open(input_file)
    doc.SaveAs(input_file.replace(".docx", ".pdf"), FileFormat=17)
    doc.Close()
    word.Quit()

def find_docs(path):
    """获取文件夹下所有docx文件列表"""
    docs= []
    for root, dirs, filenames in walk(path):
        for file in filenames:
            if file.endswith(".doc"):
                doc2docx(f"{root}\\{file}",f"{root}\\{file}x")
                docs.append(f"{root}\\{file}x")
            elif file.endswith(".docx"):
                docs.append(f"{root}\\{file}")
    docs = list(set(docs))  #去重
    # print(docs)
    return docs

from multiprocessing import Pool

def worker(input_file):
    print("{}  开始转化...\n".format(input_file))
    docx2pdf(input_file)
    print("{}  【转化完成】".format(input_file))

def main():  #多进程必须放在主程序中设置
    directory = r"C:\Users\31209\Desktop\新建文件夹"
    from multiprocessing import cpu_count
    print("cpu个数:",cpu_count())  #获取CPU个数
    ps = Pool(5) #设置线程池
    docs = find_docs(directory)
    if docs !=[]:
        print("主进程开始执行:")
        for i in docs:
            # ps.apply(worker,args=(i,))          # 同步执行
            ps.apply_async(worker,args=(i,))  # 异步执行
        ps.close() # 关闭进程池,停止接受其它进程
        ps.join()# 阻塞进程
        print("主进程终止!")

if __name__ == "__main__":
    main()



执行效果 :5个文件同时开始,转化完一个自动加入一个新任务
在这里插入图片描述

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值