Python, Windows and Printers

I do a fair amount of technical support in addition to my software development. In our small shop, we get to troubleshoot anything that is related to technology, from networks to software to printers. I think one of the most annoying aspects is trying to get printers to work the way the user wants. Another issue is setting up printers for users that have to roam from PC to PC as a part of their job. These users usually only need the printers that are in their specific location at any given time. It’s very difficult to accommodate this type of user, especially if the PCs are being used 24/7, which is true in my case. This is where Python comes in.

In this article, I’ll show you how to access the currently installed printers on a machine, change which one is the default and install another printer. I’ll also show you how to access various bits and pieces about the printers that are installed as that information can be helpful in coding up other administrative scripts.

To follow along, you’ll need Python 2.4 – 3.x and the PyWin32 package.

For our first trick of the day, let’s find out what printers are currently installed on our PC:

import win32print
printers = win32print.EnumPrinters(5)
print printers

You can use different integers in the EnumPrinters call to get more or less information. See the documentation for more information (you may need to look at MSDN as well). Anyway, here’s is a sample output:


((8388608, 'SnagIt 9,SnagIt 9 Printer,', 'SnagIt 9', ''), (8388608, 'Samsung ML-2250 Series PCL 6,Samsung ML-2250 Series PCL 6,', 'Samsung ML-2250 Series PCL 6', ''), (8388608, 'PDFCreator,PDFCreator,', 'PDFCreator', 'eDoc Printer'), (8388608, 'Microsoft XPS Document Writer,Microsoft XPS Document Writer,', 'Microsoft XPS Document Writer', ''))

As you can see, the EnumPrinters call returns a tuple with nested tuples. If I recall correctly, the last parameter will be a UNC path if the printer is a network printer. At my work place, we’ve had to decommission some servers that had printers on them and needed a way to change the user’s printer settings so that they pointed to the new path. Using the information gathered above made this much easier.

For example, if my script iterated over that list and found a printer that was using an obsolete UNC path, I could do something like this to fix it:

import win32print
win32print.DeletePrinterConnection('\\\\oldUNC\path\to\printer')
win32print.AddPrinterConnection('\\\\newUNC\path\to\printer')

An alternative way to install a printer is to use a low level command line call with the subprocess module:

import subprocess
subprocess.call(r'rundll32 printui.dll PrintUIEntry /in /q /n \\UNC\path\to\printer')

For the situation I mentioned above with roaming users, I also usually need to set the default printer so the user doesn’t accidentally print to a different department. There are two ways that I’ve found that work quite well. If you know the name of the printer, you can use the following:

import win32print
win32print.SetDefaultPrinter('EPSON Stylus C86 Series')

In the code above, I set the default to an Epson. The name should be exactly the same as the name displayed in the “Printers and Faxes” dialog in Windows (go to Start, Settings, Printers and Faxes on Windows XP). The other way to do this is with another subprocess call:

import subprocess
subprocess.call(r'rundll32 printui.dll PrintUIEntry /y /n \\UNC\path\to\printer')

There are many additional functions that win32print supports. You can start and stop print jobs, set priority levels on the print jobs, get the printer’s configuration, schedule jobs and much more. I hope you found this helpful.

Further Reading