2

Is there some way of sending output to the printer instead of the screen in Python? Or is there a service routine that can be called from within python to print a file? Maybe there is a module I can import that allows me to do this?

Timothy Lawman
  • 2,194
  • 6
  • 24
  • 33
  • 3
    Do you need something cross-platform, or platform-specific? (And, if the latter, what platform?) – abarnert Oct 25 '12 at 00:32
  • 3
    There are really plenty of resources explaining that in Google - just ask for "python print to printer" and you'll get many ideas for using `lp` or `lpr` on linux/unix/mac and/or windows modules which you could use. Proof - http://bytes.com/topic/python/answers/169648-print-printer and http://newcenturycomputers.net/projects/pythonicwindowsprinting.html – kgr Oct 25 '12 at 00:38
  • I wanted to print out a simple .txt file without any formatting requirements from a button on an interface. I was looking for a specific module name (64 bit windows machine) and function from the module. – Timothy Lawman Oct 25 '12 at 00:51

3 Answers3

4

Most platforms—including Windows—have special file objects that represent the printer, and let you print text by just writing that text to the file.

On Windows, the special file objects have names like LPT1:, LPT2:, COM1:, etc. You will need to know which one your printer is connected to (or ask the user in some way).

It's possible that your printer is not connected to any such special file, in which case you'll need to fire up the Control Panel and configure it properly. (For remote printers, this may even require setting up a "virtual port".)

At any rate, writing to LPT1: or COM1: is exactly the same as writing to any other file. For example:

with open('LPT1:', 'w') as lpt:
    lpt.write(mytext)

Or:

lpt = open('LPT1:', 'w')
print >>lpt, mytext
print >>lpt, moretext
close(lpt)

And so on.

If you've already got the text to print in a file, you can print it like this:

with open(path, 'r') as f, open('LPT1:', 'w') as lpt:
    while True:
        buf = f.read()
        if not buf: break
        lpt.write(buf)

Or, more simply (untested, because I don't have a Windows box here), this should work:

import shutil
with open(path, 'r') as f, open('LPT1:', 'w') as lpt:
    shutil.copyfileobj(f, lpt)

It's possible that just shutil.copyfile(path, 'LPT1:'), but the documentation says "Special files such as character or block devices and pipes cannot be copied with this function", so I think it's safer to use copyfileobj.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • This is what I am looking for. In order to use the above code do I need to "import os" or something first in order to access 'LPT!:' or is it built in? – Timothy Lawman Oct 25 '12 at 06:41
  • I am not sure why this information is not standard in graphical use rinformation texts? – Timothy Lawman Oct 25 '12 at 06:42
  • 1
    You don't need to import anything; as far as Python is concerned, `'LPT1:'` is just a string that you're using as a pathname, like `r'C:\foo\bar.txt'` or `'./qux.csv'`. And the reason this information isn't standard in GUI texts is that it has nothing to do with GUI functionality. (LPT1 is basically a holdover from DOS.) In a GUI, you usually want to print the contents of a window, or render an HTML or RTF to the printer, etc.; for that, you need something like the second link in kgr's comment to your question. – abarnert Oct 25 '12 at 07:11
  • Can i attach your code within a procedure called sendFile() that first generates an sqlite3 query and then writes (a list) into a file called queryResult.txt and then uses your code to send it to the printer instead of say to a memo field in Tkinter or Pmw. The function would then be called from a button with the argument command = sendFile – Timothy Lawman Oct 25 '12 at 07:21
  • 1
    Sure. But you don't really need to write it into a file in order to print it. Anything you can write to a real file, you can write to the printer file. In other words, if you have `f=open('queryResult.txt', 'w')`, everywhere you do something like `f.write(line)` you can instead (or additionally) do `lpt.write(line)`. Python doesn't see any difference between `'queryResult.txt'` and `'LPT1:'` – abarnert Oct 25 '12 at 07:33
  • abarnet: I am not sure how to ask off topic questions like in chat or something but you must be a Python developer? I am educationalist and would like to ask what Python is really used for in the outside world for my students? I know this is not he best place for it but is there anyway I can ask you on this site? – Timothy Lawman Oct 25 '12 at 08:49
  • Ah, I did not explain enough: I think I wanted to add a header and footer depending on which list (query) was used, so it would be easier to dump it all to a file first for pagination reasons: also I could inspect the file for debugging purposes ;) – Timothy Lawman Oct 25 '12 at 09:56
  • It probably isn't appropriate to ask off-topic questions here… but what the hell. Professionally, Python is heavily used for web services and back-end data processing, as an IT scripting language, and for scientific applications (especially high-energy physics). It's not quite as common for desktop apps, but see, for example, MusicBrainz Picard. It's also often embedded as an internal scripting engine (e.g., in some of the Civ games). I think Python.org has a list somewhere of major application domains where it's used. – abarnert Oct 25 '12 at 22:41
  • I'll add to the answer to show how to copy a file to the printer. – abarnert Oct 25 '12 at 22:41
  • Actually MS-DOS and Windows are the only OS's I've seen that have magic files that cause printing, and I'm not sure this gets used much on Windows anymore. I don't think Linux or Solaris or other *ix's do it this way. I haven't done enough on OS/X to say if it does or not, but I hope it doesn't - it's a weird exception to an otherwise nice, general rule. – user1277476 Oct 26 '12 at 00:03
  • 1
    @user1277476: You've got it exactly backward. Most *nixes _do_ have /dev/lp*, /dev/ttyS*, and similar files; OS X is one of the few that doesn't. See http://www.tldp.org/HOWTO/Printing-HOWTO/kernel.html for details on linux. – abarnert Oct 26 '12 at 00:10
1

Python doesn't (unless you're using graphical libraries) ever send stuff to "The screen". It writes to stdout and stderr, which are, as far as Python is concerned, just things that look like files.

It's simple enough to have python direct those streams to anything else that looks like a file; for instance, see Redirect stdout to a file in Python?

On unix systems, there are file-like devices that happen to be printers (/dev/lp*); on windows, LPT1 serves a similar purpose.

Regardless of the OS, you'll have to make sure that LPT1 or /dev/lp* are actually hooked up to a printer somehow.

Community
  • 1
  • 1
James Polley
  • 7,977
  • 2
  • 29
  • 33
  • He doesn't even need to redirect stdout to a file, he just needs to write to a file (using `f.write()`, or `print >>f` in Py2, or `print(file=f)` in Py3, etc.). – abarnert Oct 25 '12 at 00:57
1

If you are on linux, the following works if you have your printer setup and set as your default.

from subprocess import Popen
from cStringIO import StringIO

# place the output in a file like object
sio = StringIO(output_string)

# call the system's lpr command
p = Popen(["lpr"], stdin=sio, shell=True)
output = p.communicate()[0]
Pykler
  • 14,565
  • 9
  • 41
  • 50
  • This answer will be useful for programmers on a Linux system – Timothy Lawman Oct 25 '12 at 07:10
  • 2
    Actually, you can even use this on Windows if you install either cygwin, or enough of MSYS. (You'll just need to replace `"lpr"` with, e.g., `r"C:\cygwin\usr\bin\lpr.exe"` or whatever's appropriate, if you haven't put it on your Win32 path.) Also, you don't need `StringIO` here if you're printing out a textfile; just pass the file object itself as `stdin`. – abarnert Oct 25 '12 at 07:13