Python win32com.client.Dispatch循环遍历Word文档并导出为PDF; 下一个循环发生时失败

Jam*_*s N 3 python pdf docx comtypes win32com

基于这里的脚本:.doc到pdf使用python我有一个半工作脚本将.docx文件从C:\ Export_to_pdf导出到pdf到一个新文件夹.

问题是它通过前几个文件然后失败:

(-2147352567, 'Exception occurred.', (0, u'Microsoft Word', u'Command failed', u'wdmain11.chm', 36966, -2146824090), None)
Run Code Online (Sandbox Code Playgroud)

这显然是一个无益的一般错误信息.如果我使用pdb慢慢调试它,我可以遍历所有文件并成功导出.如果我也关注Windows任务管理器中的进程,我可以看到WINWORD启动然后在应该结束时结束,但是在较大的文件上,内存使用需要更长时间才能稳定.这让我觉得,当在client.Dispatch对象上调用下一个方法之前,WINWORD没有时间初始化或退出时,脚本会跳闸.

是否有一种方法可以使用win32com或comtypes来识别并等待进程启动或完成?

我的剧本:

import os
from win32com import client

folder = "C:\\Export_to_pdf"
file_type = 'docx'
out_folder = folder + "\\PDF"

os.chdir(folder)

if not os.path.exists(out_folder):
    print 'Creating output folder...'
    os.makedirs(out_folder)
    print out_folder, 'created.'
else:
    print out_folder, 'already exists.\n'

for files in os.listdir("."):
    if files.endswith(".docx"):
        print files

print '\n\n'

try:
    for files in os.listdir("."):
        if files.endswith(".docx"):
            out_name = files.replace(file_type, r"pdf")
            in_file = os.path.abspath(folder + "\\" + files)
            out_file = os.path.abspath(out_folder + "\\" + out_name)
            word = client.Dispatch("Word.Application")
            doc = word.Documents.Open(in_file)
            print 'Exporting', out_file
            doc.SaveAs(out_file, FileFormat=17)
            doc.Close()
            word.Quit()
except Exception, e:
    print e
Run Code Online (Sandbox Code Playgroud)

工作代码 - 用这个代替了try块.注意将DispatchEx语句移到for循环之外,将word.Quit()移动到finally语句以确保它关闭.

try:
    word = client.DispatchEx("Word.Application")
    for files in os.listdir("."):
        if files.endswith(".docx") or files.endswith('doc'):
            out_name = files.replace(file_type, r"pdf")
            in_file = os.path.abspath(folder + "\\" + files)
            out_file = os.path.abspath(out_folder + "\\" + out_name)
            doc = word.Documents.Open(in_file)
            print 'Exporting', out_file
            doc.SaveAs(out_file, FileFormat=17)
            doc.Close()
except Exception, e:
    print e
finally:
    word.Quit()
Run Code Online (Sandbox Code Playgroud)

Rad*_*ard 5

可能不是问题,但是调度一个单独的单词实例然后在每次迭代中关闭它是没有必要的,可能是你看到的链内存问题的原因.您只需要打开一次实例,在该实例中,您可以打开和关闭所需的所有文档.如下:

try:
    word = client.DispatchEx("Word.Application") # Using DispatchEx for an entirely new Word instance
    word.Visible = True # Added this in here so you can see what I'm talking about with the movement of the dispatch and Quit lines. 
    for files in os.listdir("."):
        if files.endswith(".docx"):
            out_name = files.replace(file_type, r"pdf")
            in_file = os.path.abspath(folder + "\\" + files)
            out_file = os.path.abspath(out_folder + "\\" + out_name)
            doc = word.Documents.Open(in_file)
            print 'Exporting', out_file
            doc.SaveAs(out_file, FileFormat=17)
            doc.Close()

    word.Quit()

except Exception, e:
Run Code Online (Sandbox Code Playgroud)

注意:在打开win32com实例和文件时要小心使用try/except,就像打开它们一样,并且在关闭它之前发生错误它将不会关闭(因为它还没有达到该命令).

您也可以考虑使用DispatchEx而不仅仅是Dispatch.DispatchEx打开一个新实例(一个全新的.exe),而我相信只使用Dispatch会尝试寻找一个打开的实例来锁定,但这个文档很模糊.如果实际上您需要多个实例(即在一个文件中打开一个文件,在另一个文件中打开一个文件),请使用DispatchEx.

至于等待,当需要更多时间时,程序应该等待该行,但我不知道.

哦! 你也可以使用,word.Visible = True如果你想能够看到实际打开的实例和文件(在视觉上看到问题可能是有用的,但在修复时将其关闭,因为它会降低速度;-)).