Печать PDF с использованием Python, win32api и Acrobat Reader 9 - PullRequest
3 голосов
/ 13 марта 2012

У меня есть отчеты, которые я отправляю в систему, которая требует, чтобы отчеты были в удобочитаемом формате PDF.Я перепробовал все бесплатные библиотеки и приложения, и единственное, что я нашел работающим, было семейством акробатов Adobe.

Я написал быстрый скрипт на python, который использует win32api для печати PDF-файла на моем принтере с помощью зарегистрированного приложения по умолчанию (Acrobat Reader 9), а затем для завершения задачи по завершении, так как acrobat любит оставлять окно открытым, когдавызывается из командной строки.

Я скомпилировал его в исполняемый файл и передал значения через командную строку (например, printer.exe% OUTFILE%% PRINTER%), после чего он вызывается в пакетном файле

import os,sys,win32api,win32print,time

# Command Line Arguments.  
pdf = sys.argv[1]
tempprinter = sys.argv[2]

# Get Current Default Printer.  
currentprinter = win32print.GetDefaultPrinter()
# Set Default printer to printer passed through command line.  
win32print.SetDefaultPrinter(tempprinter)
# Print PDF using default application, AcroRd32.exe
win32api.ShellExecute(0, "print", pdf, None, ".", 0)
# Reset Default Printer to saved value
win32print.SetDefaultPrinter(currentprinter)
# Timer for application close
time.sleep(2)
# Kill application and exit scipt
os.system("taskkill /im AcroRd32.exe /f")

Похоже, это хорошо работает для большого объема, ~ 2000 отчетов за 3-4 часа, но у меня есть некоторые, которые выпадают, и я не уверен, перегружен ли скрипт, или я должен смотреть на многопоточность или что-то еще,

Тот факт, что он обрабатывает такое большое количество без выпадения, заставляет меня поверить, что проблема не в скрипте, но я не уверен, что это проблема с хост-системой или Adobe Reader, иличто-то другое.

Любые предложения или мнения будут с благодарностью.

1 Ответ

2 голосов
/ 14 марта 2012

Исходя из вашего отзыва (win32api.ShellExecute(), вероятно, не синхронный), ваша проблема заключается в тайм-ауте: если ваш компьютер или очередь печати заняты, команда kill может прийти слишком рано.

Если ваш сценарий выполняется одновременно (то есть вы печатаете все документы сразу, а не один за другим), команда kill может даже уничтожить неправильный процесс (то есть процесс acrobat, запущенный другим вызовом сценария).

Так что тебе нужна лучшая синхронизация. Есть несколько вещей, которые вы можете попробовать:

  1. Преобразуйте это в серверный скрипт, который запускает Acrobat один раз, затем отправляет много команд печати одному и тому же процессу и впоследствии завершает работу.

  2. Используйте глобальную блокировку, чтобы убедиться, что когда-либо работает только один скрипт. Я предлагаю создать папку где-нибудь; это атомарная операция в каждой файловой системе. Если папка существует, сценарий где-то активен.

Кроме того, вам нужно знать, когда работа закончена. Для этого используйте win32print.EnumJobs().

Если это не удастся, другим решением может быть установка где-нибудь сервера Linux. В этом окне вы можете запустить сервер Python, который принимает задания на печать, которые вы отправляете с помощью небольшого скрипта Python на вашем клиентском компьютере. Затем сервер может распечатать PDF-файлы для вас в фоновом режиме.

Этот подход позволяет вам добавлять любые виды мониторинга, которые вам нравятся (отправка почты в случае сбоя или отправка сообщения о состоянии после завершения всех заданий).

...