2013-04-17 4 views
2

На основе сценария здесь: .doc to pdf using python У меня есть полурабочий скрипт для экспорта файлов .docx в pdf из C: \ Export_to_pdf в новую папку.Python win32com.client.Dispatch цикл через документы Word и экспорт в PDF; сбой при следующем цикле

Проблема заключается в том, что она проходит через первую пару документов, а затем выдает:

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

Это, по-видимому, не приносит никакой пользы общее сообщение об ошибке. Если я медленно отлаживаю его с помощью pdb, я могу прокрутить все файлы и успешно экспортировать. Если я также буду следить за процессами в диспетчере задач Windows, я вижу, что запуск WINWORD заканчивается, когда он предполагается, но в больших файлах требуется больше времени для использования памяти. Это заставляет меня думать, что сценарий отключается, когда WINWORD не успевает инициализировать или завершить работу до того, как вызывается следующий метод на объекте client.Dispatch.

Есть ли способ с 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 

Рабочий код - просто заменить блок попробовать с этим. Примечание перемещало оператор 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() 

ответ

3

может быть не проблемой, но диспетчерская отдельного экземпляра слова, а затем закрыть его в каждой итерации не является необходимым и может быть причиной проблемы нити памяти вы видите. Вам нужно только открыть экземпляр один раз и в этом экземпляре, вы можете открыть и закрыть все необходимые вам документы. Как следующее:

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: 

Примечание: Будьте осторожны при использовании Try/за исключением при открытии win32com экземпляров и файлов, как если бы вы открыть их и происходит ошибка, прежде чем закрыть это не близко (так как он не достиг того команда еще).

Также вы можете рассмотреть возможность использования DispatchEx вместо отправки. DispatchEx открывает новый экземпляр (совершенно новый .exe), в то время как я считаю, что просто использование Dispatch попытается найти открытый экземпляр, чтобы защелкнуть его, но документация об этом туманна. Используйте DispatchEx, если на самом деле вам нужно больше одного экземпляра (например, открыть один файл в одном и в одном файле в другом).

Что касается ожидания, программа должна просто ждать на этой линии, когда потребуется больше времени, но я не знаю.

Oh! вы также можете использовать word.Visible = True, если хотите, чтобы экземпляр и файлы действительно открывались (может быть полезно визуально увидеть проблему, но включить ее, когда она исправлена, потому что она будет деформировать медленные вещи ;-)).

+0

Это сделало трюк, очень спасибо - код добавлен в OP, чтобы отразить изменения. –