Printing with Python on OS X

Lately I’ve been doing more application programming. I’ve found that the best way to minimize the pain is to write as little Cocoa/Objective-C as possible. For example, here is a snippet is how you’d create a print job in Cocoa:

- (void)print:(id)sender {
[[NSPrintOperation printOperationWithView:self] runOperation];
}

- (void)printDocument:(id)sender {
// Assume documentView returns the custom view to be printed
NSPrintOperation *op = [NSPrintOperation
printOperationWithView:[self documentView]
printInfo:[self printInfo]];
[op runOperationModalForWindow:[self documentWindow]
delegate:self
didRunSelector:
@selector(printOperationDidRun:success:contextInfo:)
contextInfo:NULL];
}

- (void)printOperationDidRun:(NSPrintOperation *)printOperation
success:(BOOL)success
contextInfo:(void *)info {
if (success) {
// Can save updated NSPrintInfo, but only if you have
// a specific reason for doing so
// [self setPrintInfo: [printOperation printInfo]];
}
}

Yeah, I know, kill me now. My approach towards maintaining sanity and productivity has been to minimize these shenanigans by trying to use as little Cocoa as possible. Also, since I’ve come to [[really] disdain] Objective-C, doing the equivalent in Python was also high on my list. (That being said, I’ve also come to realize that writing Python and PyObjC is actually much worse than Objective-C and Cocoa.) What I really wanted was a pythonic way to print on OS X. The ideal scenario would be to import something and say be able to call printer.print() or something like that.

I wasn’t able to find anything like that. But, while I had originally dismissed lpr, it turned out that that was actually able to do what I needed. On OS X, lpr hooks right up to the CUPS used by the rest of the system and can be passed in not just text files, but PDFs and image files as well. Printing looks like this:

lpr -P [printer_name] file.jpg

There are several helpful commands like lproptions and lprstat that can help you with printer specific options. Here’s the CUPS documentation on Command-Line Printing and Options that’s quite useful.

So, the final code looks something like:

import popen2
popen2.popen4("lpr -P [printer] " + output_file)