【script】python实现多线程将doc、docx转pdf,doc转docx

摘要

本文讲述通过python实现多线程将当前目录下的 .doc文档转.pdf、.docx文档转.pdf,以及.doc文档转.docx(在python中,如需对word文档进行读写,只能读写docx格式的word文档)。
其中涉及到的知识点有如下几点:

  1. 通过win32com模块对office文档进行格式转化
  2. 多线程的应用及控制

模块说明

  1. threading:线程应用模块
  2. pythoncom:处理word应用,使其独立运行的api接口模块
  3. win32com:office文档处理模块,通过 “pip install pypiwin32” 安装
import os, re
import threading
import pythoncom
from win32com.client import DispatchEx

定义main部分

代码分析

  1. 在多线程程序中,因电脑性能不同,需控制线程最大并发数。以下为控制线程最大并发数的代码,用到 threading.Semaphore() 方法
semaphore = threading.Semaphore(12)
  1. 定义线程锁。不同线程之间可能在输出面板同时输出,造成输出紊乱,如:
    线程1将输出:
    who am i in thread 1
    i am A
    线程2将输出:
    who am i in thread 2
    i am B
    线程同时运行时标准输出为:
    who am i in thread 1
    i am A
    who am i in thread 2
    i am B
    而线程同时运行时可能输出:
    who am i in thread 1
    who am i in thread 2
    i am B
    i am A
    以下为控制线程独立输出的代码,用到 threading.Lock() 方法
lock = threading.Lock()
  1. 遍历指定目录下所有文件,其中 file 为文件名,a 为该文件路径, c 为该文件同一文件夹下的所有文件集
for a, b, c in os.walk(pre):
    for file in c:
  1. 判断文件名后缀是否含有 .doc ,是则为 .doc 或者 .docx 文件,否则不处理
if re.search('\.doc', file) != None:
  1. threading.Thread(target=, args=) 定义线程,target 参数指定线程运行的方法,args 参数传入运行方法的参数,start() 方法执行线程,DocToDocx和DocToPdf的作用下文中会具体说明
threading.Thread(target=WordConvertToOther.DocToDocx, args=(pre + file,)).start()

main代码

if __name__ == '__main__':
    # 控制线程最大并发数为12
    semaphore = threading.Semaphore(12)
    # 线程锁
    lock = threading.Lock()
    # 当前脚本目录绝对路径
    pre = os.path.realpath('./') + '\\'
    for a, b, c in os.walk(pre):
        for file in c:
            if re.search('\.doc', file) != None:
                # 将doc转存为docx
                threading.Thread(target=WordConvertToOther.DocToDocx, args=(pre + file,)).start()
                # 将doc、docx转存为pdf
                # threading.Thread(target=WordConvertToOther.DocToPdf, args=(pre + file, )).start()

定义doc转docx函数

代码分析

  1. 使函数在最大线程限制下运行
with semaphore:
  1. pythoncom.CoInitialize() 方法创建套间。pythoncom模块为线程和word对象创建一个套间,令其可以正常关联和执行。多线程运行office应用时需加入此模块方法,否则将出错,非多线程则不需要。之后的 pythoncom.CoUninitialize() 方法则用以释放套间资源
pythoncom.CoInitialize()
  1. 通过 DispatchEx(‘Word.Application’) 方法启动office应用程序,相当于在windows下打开office
word = DispatchEx('Word.Application')
  1. 通过 word.Documents.Open() 方法启动具体的某个文档文件
doc = word.Documents.Open(docpath)
  1. doc.SaveAs() 为将打开的doc存储为docx的主要方法。其中 re.sub 方法将路径中文件名的doc替换为docx,FileFormat 指定保存的文件格式,等于 12 保存为docx、等于 17 保存为pdf
doc.SaveAs(re.sub('.doc$', '.docx', docpath), FileFormat=12)
  1. 无论doc文档执行结果如何,都需让office应用程序关闭,否则将会在后台中继续运行,占用系统资源
word.Quit()

函数代码

    def DocToDocx(docpath):
        '''将doc转存为docx'''
        with semaphore:
        	lock.acquire()
            try:
                # CoInitialize初始化,为线程和word对象创建一个套间,令其可以正常关联和执行
                pythoncom.CoInitialize()
                # 用DispatchEx()的方式启动MS Word或与当前已执行的MS Word建立连结
                word = DispatchEx('Word.Application')
                # 打开指定目录下doc文档
                doc = word.Documents.Open(docpath)
                # 将打开的doc文档存储为docx
                doc.SaveAs(re.sub('.doc$', '.docx', docpath), FileFormat=12)
                # 关闭doc文档
                doc.Close()
            except:
                # 报错则输出报错文件
                print(docpath + ':无法打开')
            else:
                # 无报错输出转换完成
                print(os.path.basename(docpath) + " : 转换完成")
            finally:
                # 关闭office程序
                word.Quit()
                # 释放资源
                pythoncom.CoUninitialize()
            lock.release()

定义doc转pdf函数

函数代码

这里与doc转docx类似,直接附上函数代码:

    def DocToPdf(docpath):
        '''将doc、docx转存为pdf'''
        with semaphore:
        	lock.acquire()
            try:
                pythoncom.CoInitialize()
                word = DispatchEx('Word.Application')
                doc = word.Documents.Open(docpath)
                doc.SaveAs(re.sub('\.doc.*', '.pdf', docpath), FileFormat=17)
                doc.Close()
            except:
                print(docpath + ':无法打开')
            else:
                print(os.path.basename(docpath) + " : 转换完成")
            finally:
                word.Quit()
                pythoncom.CoUninitialize()
            lock.release()

完整代码

import os, re
import threading
import pythoncom
from win32com.client import DispatchEx

class WordConvertToOther:
    def DocToDocx(docpath):
        '''将doc转存为docx'''
        with semaphore:
        	lock.acquire()
            try:
                # CoInitialize初始化,为线程和word对象创建一个套间,令其可以正常关联和执行
                pythoncom.CoInitialize()
                # 用DispatchEx()的方式启动MS Word或与当前已执行的MS Word建立连结
                word = DispatchEx('Word.Application')
                # 打开指定目录下doc文档
                doc = word.Documents.Open(docpath)
                # 将打开的doc文档存储为docx
                doc.SaveAs(re.sub('.doc$', '.docx', docpath), FileFormat=12)
                # 关闭doc文档
                doc.Close()
            except:
                # 报错则输出报错文件
                print(docpath + ':无法打开')
            else:
                # 无报错输出转换完成
                print(os.path.basename(docpath) + " : 转换完成")
            finally:
                # 关闭office程序
                word.Quit()
                # 释放资源
                pythoncom.CoUninitialize()
            lock.release()

    def DocToPdf(docpath):
        '''将doc、docx转存为pdf'''
        with semaphore:
        	lock.acquire()
            try:
                pythoncom.CoInitialize()
                word = DispatchEx('Word.Application')
                doc = word.Documents.Open(docpath)
                doc.SaveAs(re.sub('\.doc.*', '.pdf', docpath), FileFormat=17)
                doc.Close()
            except:
                print(docpath + ':无法打开')
            else:
                print(os.path.basename(docpath) + " : 转换完成")
            finally:
                word.Quit()
                pythoncom.CoUninitialize()
            lock.release()

if __name__ == '__main__':
    # 控制线程最大并发数为12
    semaphore = threading.Semaphore(12)
    # 线程锁
    lock = threading.Lock()
    # 当前脚本目录绝对路径
    pre = os.path.realpath('./') + '\\'
    for a, b, c in os.walk(pre):
        for file in c:
            if re.search('\.doc', file) != None:
                # 将doc转存为docx
                # threading.Thread(target=WordConvertToOther.DocToDocx, args=(pre + file,)).start()
                # 将doc、docx转存为pdf
                threading.Thread(target=WordConvertToOther.DocToPdf, args=(pre + file, )).start()

参考文献

  • https://www.jianshu.com/p/4fa504c720c1
  • http://yshblog.com/blog/57

你可能感兴趣的:(python编程,python,doc转docx,doc转pdf,docx转pdf,多线程)