[Tutor] working code for adding line numbers -- request for
criticism
Lloyd Kvam
pythonTutor at venix.com
Sat Apr 17 17:18:35 EDT 2004
On Sat, 2004-04-17 at 15:56, Brian van den Broek wrote:
> 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.)
Use Alt-G to jump to a line. (Works for me in Linux & WinNT)
> 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
> accepted.)
>
The fileinput module makes it easy to process lists of input files or
piped input through stdin. That's usually better than prompting for
filenames in your program.
> Right near the top, there is a comment where I have a question about how to do
> it better.
Use triple quotes for multi-line strings. These can break the indent
rules. I adjusted your code down below.
One other thing to note, Python now has an enumerate function which will
provide a counter as you iterate. This allows you to write:
for i,line in enumerate(sfile):
and helps avoid errors where you forget to initialize the counter or
fail to increment the counter.
>
> 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():
filename_prompt = '''What file would you like to process?
(Specify a full path if it is not in the current working directory)
'''
> f = raw_input(filename_prompt)
> # 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():
> print
> 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
> try:
> m = int(m)
> if m > 0: return m
> else:
> print o; return default
> except:
> print o; return default
>
> default = 5
> print
> print 'Yout current working directory is ' + os.getcwd()
> print
>
> sfilename = get_filename()
> # 'sfilename', etc. for source file name, etc.
> # Likewise for 'tfilename' and taget file name.
> print
> 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()
> print
>
> 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)
> tfile.write(line)
> i = i + 1
>
> tfile.close()
> sfile.close()
>
>
> _______________________________________________
> Tutor maillist - Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
--
Lloyd Kvam
Venix Corp.
1 Court Street, Suite 378
Lebanon, NH 03766-1358
voice: 603-653-8139
fax: 801-459-9582
More information about the Tutor
mailing list