Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python's win32api only printing to default printer

I'm trying to use win32api to output a PDF document to a particular printer.

win32api.ShellExecute(0, "print", filename, '/d:"%s"' % printername, ".", 0)

filename is a full pathname to the file, and printname is the name of the target printer I get by going through the output of win32api.EnumPrinters(6).

The file is sent to the Windows default printer even if printername is the name of a different target (my expectation is that passing a specific printer would send the named file to that printer, rather than the default).

Any hints as to what I'm doing wrong? Is there a different way of generically printing a PDF file to a specific printer? Barring all else, is there a way of temporarily changing the default printer from my program?

like image 884
Inaimathi Avatar asked Sep 27 '12 17:09

Inaimathi


3 Answers

MikeHunter's answer was a decent starting point.

The proposed solution is calling out to Acrobat or Acrobat Reader to do the actual printing, rather than going through the win32api. For my purposes, this is sufficient:

from subprocess import call

acrobat = "C:\Program Files\Adobe\Acrobat 7.0\Acrobat.exe" ## Acrobat reader would also work, apparently
file = "C:\path\to\my\file.pdf"
printer = "Printer Name Goes Here"

call([acrobat, "/T", file, printer])

That starts up Acrobat, and prints the given file to the named printer even if it's not the Windows default. The first print job processed this way takes a few seconds (I'm assuming this is the Acrobat service being started and cached in memory), subsequent jobs print instantly. I have not done any kind of load testing on this, but I assume the call is less than trivial, so don't trust it for massive throughput.

like image 99
Inaimathi Avatar answered Sep 21 '22 15:09

Inaimathi


I use SumatraPDF to achieve a similar solution (Python 3) as user Inaimathi posted:

import time
from subprocess import call

start = time.perf_counter()
sumatra = "C:\\Program Files\\SumatraPDF\\SumatraPDF.exe"
file = "C:\\Users\\spiderman\\Desktop\\report.pdf"

call([sumatra, '-print-to-default', '-silent', file])
end = time.perf_counter()
print("PDF printing took %5.9f seconds" % (end - start))

The list of command-line arguments you can pass to SumatraPDF is here.

like image 45
Miguel Rentes Avatar answered Sep 19 '22 15:09

Miguel Rentes


I'm trying to print any old file to a specific printer, so these answers did not help me. However, I did find the perfect solution. Windows has a canonical verb called printto that does not show up in the context menu. It is used as a way for users to drag and drop a document onto a printer to enable printing in that manner. We can use that feature; the second argument is the name of the printer. I could never get the /d: parameter to work correctly in conjunction with the print canonical verb, but this solution solved it for me. I put the printername in quotes in case there are spaces in it.

win32api.ShellExecute(0, "printto", filename, f'"{printername}"', ".", 0)
like image 34
Bobort Avatar answered Sep 22 '22 15:09

Bobort