[Tutor] working code for adding line numbers -- request for criticism

Brian van den Broek bvande at po-box.mcgill.ca
Sat Apr 17 15:56:43 EDT 2004

Hi all,

having learned the lessons of posting under-thought-out questions and not 
wishing to further test the goodwill of those on the list, I have code to post 
this time! (Thanks again for past tolerance.)

I've found that traceback errors identified by line numbers can be tricky to 
track down without line number indications in the code or the editor. (IDLE 
doesn't seem to provide for line numbers, and it's no fun counting line on 
screen in a long file.) So, I wrote a script to take a file and output a file 
with line number comments added. (BTW, is there a module that will do this? If 
so, no harm, as the exercise was useful, but I'd probably be better off with a 
module than my script.)

I've worked through a way to do it. But I'd very much appreciate being told 
where and how this code is kludgey and could be improved. As I said, it seems to 
work, but I don't think it will win any prizes for beauty or being Pythonic. If 
asking for such a critique is over-imposing, I understand. (My aim in asking is 
to break bad habits before they become entrenched. Brutal criticism is happily 

Right near the top, there is a comment where I have a question about how to do 
it better.

One case where I know it does not work is for files without any extension at 
all. I want file.txt to come out as file_numbered.txt but file comes out as 
fil_numberede. I can see how to fix that (by constructing the output filename 
differently depending on whether the filename contains a '.' or not, but it 
didn't seem worth doing.

I also understand that adding comments to arbitrary lines may violate syntax 
(say, by adding a comment to other than the last line of a long string). It also 
may well take lines past 80 characters. Neither worry me; the line number 
comments are being added to a new file intended for inspection rather than 
running. Also, it is likely OS specific to DOS/Windows. That's what I run (for 
now) and what I can test on.

Thanks and best to all,

Brian vdB

import os.path

def get_filename():
     f = raw_input('What file would you like to process?  \n \
     (Specify a full path if it is not in the current working directory) \n')
     # This makes for ugly screen output. How can I left allign the output
     # without breaking the function def's indetation?
     return f

def get_multiple():
     m = raw_input('By default, I mark each %i lines with line numbers.\n \
     Would you like a different choice of line multiples to mark?  \n \
     If so, enter a positive whole number now. \n \
     (All other choices will result in the use of the default value of %i)\
     \n' %(default, default))
     o = 'Your input was not a positive integer. \n \
     The default multiple of %i will be used instead' %default
         m = int(m)
         if m > 0: return m
             print o; return default
         print o; return default

default  = 5
print 'Yout current working directory is ' + os.getcwd()

sfilename = get_filename()
# 'sfilename', etc. for source file name, etc.
# Likewise for 'tfilename' and taget file name.
while os.path.isfile(sfilename) == False:
     print "I'm sorry, but you have specified a non-existent file path.\
     Please try again. (You can press CTRL-C to end if you prefer)"
     sfilename = get_filename()

multiple = get_multiple()

sfile = file(sfilename)
sfile_base = os.path.basename(sfilename)
i = sfile_base.rfind('.')
tfile_base = sfile_base[:i] + '_numbered' + sfile_base[i:]
# inserts '_numbered' immediately before the extension (if any) of the filename
# otherwsie before the last character. A bit broken, but doesn't matter.
tfilename = os.path.join(os.path.dirname(sfilename), tfile_base)

# Prints output file name and location
if os.path.dirname(tfilename) == '': dirname = os.getcwd()
# To ensure that the directory is displayed in print below. Needed as
# os.path.dirname(tfilename) == '' when the dirname is the cwd
else: dirname = os.path.dirname(tfilename).capitalize()
# Capitalize ensures that drive letter displays in DOS convention
target = (tfile_base, dirname)
print 'Your numbered file will be %s in the directory %s' %target

tfile = file(tfilename, 'w')
i = 1
for line in sfile:
     if i%multiple == 0 and line[-1] == '\n':
         line = line[:-1] + '  # ' + str(i) + '\n'
     if i%multiple == 0 and line[-1] != '\n':
         line = line + '  # ' + str(i)
     i = i + 1


More information about the Tutor mailing list