Hi,

Im relatively experienced with the Python language, but i have a smaller knowledge of its modules etc. Im familiar with Tkinter, basic sockets, basic threading, math ( i know the most about).

Im looking for a way to print to a printer. I can read from files easily - but what i want to do is to have each file printed with line numbers ( with wordwrap), and to add the document name at the top, and "Page x of y" at the bottom.

The page name I need to format ( it will contain the full path, minus a specified section whic i can store in a variable to display on each page).

Visual example:

------------------------------------------+
| /dir/file.txt
|1 code
|2 code
|3 code
|
|...
|
| page 1 of 5
+----------------------------------------+


well thats the idea.

I dont know how to print to a printer - liek I can in Visual Basic ( thought I hevent figured out the line numbering etc in that either).

Is ther a particular module/library I need to install to be able to print form python? I am using Windows XP, and Python 2.5.1.

Thanks for any and all help in advance.

Recommended Answers

All 8 Replies

To print directly to the printer, you have to access the device driver. I'm on linux so can't help you there. A more common method for simple files that do not have to be formatted is to write the output to a file and use os.system() or subprocess with a system call to print the file. In linux it is
os.system( "lpr filename")
In the dark ages when I used to use Windows it was just "print full_path_filename" which if it works it all the time you have to spend on this. The print command (if there is one) may also have an option to add line numbers when you print. Google should help you find more if no one here can be of more help.

Some of the basics of sending a text string to the printer are in the Python code snippet at:
http://www.daniweb.com/code/snippet399.html

If you have a Python code file like this ...

# days2xmas.py
# calculate days till xmas of 2008

import datetime as dt

now = dt.date.today()
# change the year for other years
xmas = dt.date(2008, 12, 25)
time2xmas = xmas - now
print "There are %d days till xmas 2008!" % time2xmas.days

You can load the file and build up a string you can send to the printer prefixed with line numbers this way...

# add line numbers to a code string

my_str = ""
linecount = 1
# load your code file
for line in file("days2xmas.py", "r"):
    line = "%3d  %s" % (linecount, line)
    my_str += line
    linecount += 1

print my_str

"""
my output -->
  1  # days2xmas.py
  2  # calculate days till xmas of 2008
  3  
  4  import datetime as dt
  5  
  6  now = dt.date.today()
  7  # change the year for other years
  8  xmas = dt.date(2008, 12, 25)
  9  time2xmas = xmas - now
 10  print "There are %d days till xmas 2008!" % time2xmas.days
"""

Breaking a long code string into page strings with page number, title and wordwrap is just a matter of string handling. Lots of work and a good exercise.

hmmm ok.

Ive printed off and i plan on going through that turoail'/ code on the link you provoded (thanks). Im still not sure about the line numbering. As im sure your all aware, its easy to loop through a file and then attach each line to a dictionary with the first characters being a line number(increment) and then a tab. Thats easy.

My main thing is that it looks like i have to manually wordwrap my printing - which is the hard part.

can anyone suggest a method for this?

Thanks

I found this word wrap function somewhere:

def wrap(text, width):
    """
    A word-wrap function that preserves existing line breaks
    and most spaces in the text. Expects that existing line
    breaks are linux style newlines (\n).
    """
    def func(line, word):
        nextword = word.split("\n", 1)[0]
        n = len(line) - line.rfind('\n') - 1 + len(nextword)
        if n >= width:
            sep = "\n"
        else:
            sep = " "
        return '%s%s%s' % (line, sep, word)
    text = text.split(" ")
    while len(text) > 1:
        text[0] = func(text.pop(0), text[0])
    return text[0]


# 2 very long lines separated by a blank line
msg = """Arthur:  "The Lady of the Lake, her arm clad in the purest \
shimmering samite, held aloft Excalibur from the bosom of the water, \
signifying by Divine Providence that I, Arthur, was to carry \
Excalibur. That is why I am your king!"

Smarty:  "Listen. Strange women lying in ponds distributing swords is \
no basis for a system of government. Supreme executive power derives \
from a mandate from the masses, not from some farcical aquatic \
ceremony!\""""

# example: make it fit in 40 columns
print wrap(msg,40)

# result is below
"""
Arthur:  "The Lady of the Lake, her arm
clad in the purest shimmering samite,
held aloft Excalibur from the bosom of
the water, signifying by Divine
Providence that I, Arthur, was to carry
Excalibur. That is why I am your king!"

Smarty:  "Listen. Strange women lying in
ponds distributing swords is no basis
for a system of government. Supreme
executive power derives from a mandate
from the masses, not from some farcical
aquatic ceremony!"
"""

In Linux, one can use popen to access the print spooler, which then takes care of scheduling and printing the job. Does anyone know if this works on Windows using the "print" command?
pr=os.popen("lpr", "w")
pr.write("Write this line directly to the print spooler\n")
pr.close()

Ok,

Nowe I hate to have to ask, but is there a default width of column size that would fit A4 paper? If i know what my margins from side will be, how would I then implement that into the code?

I assume that the correct wat to wordwrap would be to alter each lines left align/margin? If now is there another way.

Sorry abot this, Im not sued to overly formatting my data, expecially for a printer.


Thanks for all your help, its absoutely fantastic.

There is generally 8, 10, or 12 characters printed per inch using "normal" fonts. If you want the columns to line up then you have to use a monospaced/fixed width font instead of a proportional font. With a proportional font you can align the columns by inserting tabs but how it prints depends on the default tab size. You will have to print a test line or two to see what the default font for your printer does. i.e. send something like
....:....1....:....2....:....3....:....4....:....5....:....6....:....7....:....8
the above is for characters available per line (including margins) so length=available-margins
ilili
mwmwm <----- The "i" will be over the "m" if it is a fixed width font, and "l" over "w"

To get fancier than your printer's default type style, you would have to use a markup language like postscript or html, although some printers have their own control language and can print more than one default font.

Ok,

I looked at some tutorials on *tgolden* which was recomended to me by a friend.

There is one tutorial that walks through opening the file through teh shellExecute function, and it opens with its default program.

Im not overly familiar with command prompt - but is there a way to open that file with a specific program.

ie - what i want to do is loop through each file, and open/print it with notepad ++ or another editer depending on the file type. I can list the file types and the fiull path to the executable thats not an issue - but the command shell code is.

Is this possible or do i still have to manually print it through pythons win32print?


Thanks for all your help so far :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.