BCL easyPDF SDK
easyPDF SDK Usermanual
PDF Creator Programming API  |  Download Free Trial  |  Contact Us to Purchase

Native Python Printer API

Usage

The native Python API, which is written in Python 3, is a thin interface around a binary executable. It is very similar to the native .NET API, with the exception of some language-specific differences.

Note: there is no native Python 2 API. That was a very different language than Python 3.

In order to use easyPDF, just import the library by adding import easyPDFPrinter. The Printer SDK is inside the easyPDFPrinter. namespace. easyPDFPrinter.py can be found under C:\Program Files\Common Files\BCL Technologies\easyPDF 8.

When an error occurs, an exception of type PrinterException is thrown.

The Printer class has a destructor, which means it is automatically disposed when the object goes out of scope. That makes memory management trivial, just make sure you are not holding on to the variable when you are no longer using the SDK.

If the customer's application crashes, the system automatically closes all pipes belonging to the process, which means all related worker processes automatically quit as well.

The minimal Python sample code looks like this:

import easyPDFPrinter
printer = easyPDFPrinter.Printer()
try:
   printJob = printer.getPrintJob()
   printJob.PrintOut("c:\\test\\input.doc", "c:\\test\\output.pdf")
except easyPDFPrinter.PrinterException as ex:
   print(ex)

Printer's constructor is designed to never throw exceptions. That's because it does not launch a worker process and does not create a named pipe, it merely initializes a few variables to their default values. In other words, creating a Printer object is extremely lightweight, like creating a Color object.

However, as soon as you do anything else, it instantly launches a worker process.

Notification Events

Notification events in the native Python API are slightly different than in the native .NET API. Here is an example that catches OnPageStart, which is called before printing each page:

def PageStart(uid, pageNumber):
   print("Page %d..." % (pageNumber + 1))
   return easyPDFPrinter.prnMonitorResponse.PRN_MON_CONTINUE_CONVERSION

printer = easyPDFPrinter.Printer()
try:
   monitor = printer.getPrintJobMonitor()
   monitor.OnPageStart = PageStart
   printJob = printer.getPrintJob()
   printJob.PrintOut("c:\\test\\input.doc", "c:\\test\\output.pdf")
except easyPDFPrinter.PrinterException as ex:
   print(ex)

Alternatively, the event handler can be a class method:

class Handler:
   def PageStart(self, uid, pageNumber):
      print("Page %d..." % (pageNumber + 1))
      return easyPDFPrinter.prnMonitorResponse.PRN_MON_CONTINUE_CONVERSION

printer = easyPDFPrinter.Printer()
handler = Handler()
try:
   monitor = printer.getPrintJobMonitor()
   monitor.OnPageStart = handler.PageStart
   printJob = printer.getPrintJob()
   printJob.PrintOut("c:\\test\\input.doc", "c:\\test\\output.pdf")
except easyPDFPrinter.PrinterException as ex:
   print(ex)

Launch Timeout

Launching the worker process and connecting the named pipe should happen very fast, in milliseconds. However, under an abnormally heavy load, the computer may not have enough cycles to perform this task in a timely fashion.

The Native Python API has an internal timeout built-in. The default value is 1 minute. This is because a server may momentarily slow down so much that it is not responding for seconds, but it usually recovers after a while.

The default timeout value can be changed via Printer's launchTimeout member (in milliseconds). This must be performed immediately after the creation of the Printer object.

printer = easyPDFPrinter.Printer()
try:
   printer.launchTimeout = 60000
   printJob = printer.getPrintJob()
   printJob.PrintOut("c:\\test\\input.doc", "c:\\test\\output.pdf")
except easyPDFPrinter.PrinterException as ex:
   print(ex)

Upon timeout an exception is thrown, and the SDK cannot be used. Another attempt may be made later.

Server-Side Operation

Printing from the server side has always required easyPDF Loader, a special service that helps execute functions under a different user account.

The Native Python SDK offers two possible solutions for server-side printing. One is called the Loader Service, and the other one is called Impersonation.

Customers who are printing from a web server or a system service should study both alternatives, and decide which one they prefer.

Both the Loader Service and Impersonation are under Printer's loaderSettings member. This must be set up immediately after the creation of the Printer object.

For example, here is how to use Impersonation:

printer = easyPDFPrinter.Printer()
try:
   printer.loaderSettings.useLoader = True
   printer.loaderSettings.userName = "easyPDF8User"
   printer.loaderSettings.password = "your password comes here"
   printJob = printer.getPrintJob()
   printJob.PrintOut("c:\\test\\input.doc", "c:\\test\\output.pdf")
except easyPDFPrinter.PrinterException as ex:
   print(ex)

PrinterMonitor

PrinterMonitor is a desktop-only feature designed to enable traditional File > Print functionality in a desktop environment. It also supports notification callback events, and the output PDF files can be named programmatically.

Use PrintJobMonitor, instead of PrinterMonitor, to monitor a PrintJob.PrintOut function. PrinterMonitor is only for enabling interactive prints.

PrinterMonitor should never be used on the server side, or from a service. It is not compatible with Impersonation or the Loader Service.

You can start the printer monitor by calling printer.getPrinterMonitor(). The printer monitor will only stop when the printer object is deleted (garbage collected). PrinterMonitor is not blocking, because it is running in another thread in an external process.

It is a good idea to specify the output file path before you begin printing:

printer = easyPDFPrinter.Printer()
try:
   monitor = printer.getPrinterMonitor()
   monitor.setOutputFileName("c:\\test\\output.pdf")

   input("You can begin printing now. When finished, press Enter to stop the printer monitor.\n")

except easyPDFPrinter.PrinterException as ex:
   print(ex)

The same file name is used for all subsequent operations. If you don't explicitly set the file name, it is automatically chosen, usually based on the input file name. Be careful — even if you normally have access to a directory, the printing application may not.

You may also print programmatically after the printer monitor is started. However, it is preferred to use GenericPrintJob.PrintOut for all non-interactive printing.

You may choose to listen on print progress notification events. It takes a few extra lines to set that up:

def PrinterInit(uid, info):
   print("Init")
   info.OutputFileName = "c:\\test\\output.pdf"
   return easyPDFPrinter.prnMonitorResponse.PRN_MON_CONTINUE_CONVERSION
def PrinterUpdate(uid, info):
   print("Update")
   return easyPDFPrinter.prnMonitorResponse.PRN_MON_CONTINUE_CONVERSION
def PrinterStart(uid):
   print("Start")
   return easyPDFPrinter.prnMonitorResponse.PRN_MON_CONTINUE_CONVERSION
def PageStart(uid, pageNumber):
   print("Page %d..." % (pageNumber + 1))
   return easyPDFPrinter.prnMonitorResponse.PRN_MON_CONTINUE_CONVERSION
def PrinterEnd(uid, err):
   print("End")
   return easyPDFPrinter.prnMonitorResponse.PRN_MON_CONTINUE_CONVERSION

printer = easyPDFPrinter.Printer()
try:
   monitor = printer.getPrinterMonitor()
   monitor.OnPrinterInit = PrinterInit
   monitor.OnPrinterUpdate = PrinterUpdate
   monitor.OnPrinterStart = PrinterStart
   monitor.OnPageStart = PageStart
   monitor.OnPrinterEnd = PrinterEnd

   input("You can begin printing now. When finished, press Enter to stop the printer monitor.\n")
except easyPDFPrinter.PrinterException as ex:
   print(ex)

The example above shows an alternative way of setting up the output file name.

If you want to pop up the Save dialog and let the user choose the output file name, you may add the following lines:

def PrinterInit(uid, info):
   print("Init")
   info.OutputFileName = "c:\\test\\DefaultOutputFileName.pdf"
   info.PDFSetting.UiAlerts = True
   info.PDFSetting.UiFileDialog = True
   info.PDFSetting.UiPropertiesDialog = True
   return easyPDFPrinter.prnMonitorResponse.PRN_MON_CONTINUE_CONVERSION

If you specify OutputFileName, that's going to be the default. If you do not, the default file name is automatically generated based on the print job's name. Either way, the user will get a chance to override it.

Please note that callback notifications are coming from a worker thread, which is listening in the background. This thread is generally sleeping while there are no notifications. The thread starts when printer.getPrinterMonitor() is called, and it only stops when the printer object is garbage collected (the instance goes away, or set to None).