looping through a file

Alex Martelli aleax at aleax.it
Wed Apr 30 08:01:30 EDT 2003


<posted & mailed>

Psybar Phreak wrote:

> hi all - ive just started with python (after having done java and c) and
> am
> having a little bit of trouble with the script.  Im using as a login
> script.
> 
> There's a users.dat file in the format
> user1
> user1password
> user2
> user2password
> ... etc

So far so good.

> 
> at the moment - the code i work, only checks the first and second lines
> (ie.
> details of user1).  but it appears that python doesn't have a do...
> while... until loop.

Right, it doesnt't -- and indeed you don't need it for this purpose.


> #!/usr/local/bin/python
> 
> import cgi, string
> 
> form = cgi.FieldStorage()
> 
> if form.has_key('usernameField') and form.has_key('passwordField'):
>          users_username = string.strip(form['usernameField'].value)
>          users_password = string.strip(form['passwordField'].value)
> 
> InFile = open('users.dat', 'r')
> 
> file_username = string.strip(InFile.readline())
> file_password = string.strip(InFile.readline())

If the InFile is empty or has only one line this sets file_username
and/or file_password to empty strings (just as it does for all-white
lines, e.g. lines consisting just of a \n ["empty" ones]).  OK.

You're also using the string module -- that was necessary back in
the dark ages of Python 1.5.2, but with modern versions of Python
you should best use string methods instead.

> 
> authorised = 0
> 
> while file_username and file_password:
>        if file_username == users_username:
>               if file_password == users_password: # correct
>              authorised = 1
>       break
>               else:                               # login matched but not
> password
>                     file_username = InFile.readline()

You're omitting the strip calls here -- different semantics
from before.

>              file_password = InFile.readline()
>        else: # neither match
>               file_username = InFile.readline()
>               file_password = InFile.readline()

How complicated.  If the InFile can be expected to have a sensible
dimension, say no more than a few hundreds of KB at most (and in this
case that seems only reasonable!), just read all of its lines as
once with the readlines call and then index into the resulting list
of lines.  For example:

InFile = open('users.dat', 'r')
lines = InFile.readlines()
InFile.close()

for i in range(0, len(lines), 2):
    file_username = lines[i].strip()
    file_password = lines[i+1].strip()
    if file_username==users_username and file_password==users_password:
        authorized = 1
        break
else:
    authorized = 0

This may have slightly different semantics when InFile has an odd
number of lines, but I doubt you need to worry about that anyway.

I think this will most likely solve your practical problems.  However,
supposing for the sake of argument that InFile could be SO large that
reading it all at once with readlines would be a problem (say, tens
of megabytes), you could solve that too, for example, using again
modern Python (2.2 or better in this case):

InFile = open('users.dat', 'r')

for line in InFile:
    file_username = line.strip()
    file_password = InFile.next().strip()
    if file_username==users_username and file_password==users_password:
        authorized = 1
        break
else:
    authorized = 0

InFile.close()

Once again different semantics (an exception...) for odd numbers
of lines in users.dat -- you can use try/except StopIteration: around
the explicit call to InFile.next to deal with this as you wish.


Alex





More information about the Python-list mailing list