3

So basically I have a program which can create a users username and password in a document and search for the password used with the username that is input by the person using the program.

For example: The programs asks me to input a username I enter: '13'. Under 13 in the text document is 'sadfsdfsdf'. I want the program to skip to below the 'Username: 13' and read and print 'Password: sadfsdfsdf'.

note that I have multiple usernames and passwords In the .txt file

u = 'Username: '

Thanks in advance!

def SearchRecordProgram():
    while True:
                    user_search = input("Please enter the username you wish to see the password for: ")
                    full_user = u + user_search
                    if full_user in open('User_Details.txt').read():
                            print(" ")
                            print ("Username found in our records")
                            print(" ")
                            print(full_user)
                            break
                    else:
                            print("Username entered does not match our records")
b4sh
  • 55
  • 1
  • 9

4 Answers4

1

So, imagining your file is like so:

Username : 13
Password : sadfsdfsdf
Username : 15
Password : Lalalala

You can parse it (with regular expressions) like so:

import re  #  regular expression module
regex = re.compile("Username :(.*)\nPassword :(.*)")

# read text from file
with open(filePath,'r') as f:
    text = f.read() 

u_pass = regex.findall(text)
# [(' 13', ' sadfsdfsdf'), (' 15', ' Lalalala')]

user_dict = {u:password for u,password in u_pass}
#  {' 13': ' sadfsdfsdf', ' 15': ' Lalalala'}

Now you can get the password of someone by asking for the password of that user :

# given username and password_input

if username in user_dict and user_dict[username] == password_input:
# if username exists and password okay
    print "Authentication succeeded."
Jiby
  • 1,865
  • 1
  • 13
  • 22
0

Maybe not the pretties, but something like this will work:

with open(users_file, "r") as f:
    lines = f.read()

def get_password(user_id):
    entries = iter(lines.splitlines())
    for entry in entries:
        if(entry.startswith("{}:{}".format(prefix, user_id))):
            return next(entries)

print "Password:", get_password("13")
Will Hogan
  • 909
  • 4
  • 9
0
def SearchRecordProgram():
    while True:
        user_search = input("Please enter the username > ")

        file = open('User_Details.txt')
        usernames = file.readlines()  # Read file into list
        file.close()

        if user_search in usernames: # Username exists
            print ('Found Username')
            password = usernames[usernames.index(user_search)+1]
            print ('Password is: ' + password)   

            break  # Exit loop

         else:  # Username doesn't exist
             print("Username entered does not match our records")

Note that this will not work if a password happens to be a username, e.g:

user1
password1
user2
user3  # This is the password for user3
user3
password3

If you search for "user3" this code will output "user3" as the password for "user3" because it finds the first instance of "user3" (line 4) and then looks to the next line (line 5), which is the next username.

Even worse, if "user3" is the last line in the file, it will end with an error because there are no more lines. You could add a check that the index of the found username is even (i.e. index 0, 2, 4, 8) with this code:

if not usernames.index(user_search) % 2:  # Checks the remainder after / by 2.
                                          # If it's 0 then it's an even index.
    password = usernames[usernames.index(user_search)+1]
    print ('Password is: ' + password)   

but there isn't much you can do if this happens.

However, you could manipulate the file of usernames to only have usernames like this:

lst = [0, 1, 2, 3, 4, 5, 6, 7]
print (lst[0::2])

which prints

[0, 2, 4, 6]

So the code could be changed to this:

def SearchRecordProgram():
    while True:
        user_search = input("Please enter the username > ")

        usernames = open('User_Details.txt').readlines()  # Read file into list

        if user_search in usernames[0::2]: # Username exists
            print ('Found Username')
            password = usernames[1::2][usernames[0::2]].index(user_search)]
            print ('Password is: ' + password)   

            break  # Exit loop

         else:  # Username doesn't exist
             print("Username entered does not match our records")

Here is a breakdown

password = usernames[1::2]  # Gets the odd items (passwords)
                          [  # Get index item. The index returned from searching
                             # the usernames will be the same as the index needed
                             # for the password, as looking at just the odd items:
                             # [0, 2, 4, 6]
                             # [1, 3, 5, 7] - even has the same index as next odd.
                           usernames[0::2] # Gets even items (usernames)
                                          ].index(user_search)]
                                          # Only searches the usernames. This
                                          # means passwords being the same is not
                                          # an issue - it doesn't search them
Tim
  • 2,563
  • 1
  • 23
  • 31
  • 2
    This leaves the file open and stores the whole file into memory (which probably isn't an issue, but could easily be avoided regardless). – Markus Meskanen Oct 17 '15 at 21:34
0

When you want to open a file, you should almost always use the with statement:

with open('User_Details.txt') as read_file:
    # Do reading etc. with `read_file` variable

This will ensure that any errors are being handled correctly and the file is not left open.

Now that the file is open, we need to loop through each line until we find one that matches our username. I hope you know how for loop works:

username = 'Username: 13'  # Get this however you want
with open('User_Details.txt') as read_file:
    for line in read_file:
        line = line.strip()  # Removes any unnecessary whitespace characters
        if line == username:
            # We found the user! Next line is password

And we need to get the next line which contains the password. There are many ways to get the next line, but one simple way is to use the next() function which simply gets us the next element from an iterable (the next line from a file in this case):

username = 'Username: 13'
with open('User_Details.txt') as read_file:
    for line in read_file:
        line = line.strip()
        if line == username:
            password = next(read_file)
            break  # Ends the for loop, no need to go through more lines

Now you have a password and an username, and you can do whatever you want with them. It's often a good idea to have the inputs and outputs outside of your program's logic, so don't print the password right inside the for loop, but instead just receive it there and then do the printing outside.

You might even wanna turn the whole search logic into a function:

def find_next_line(file_handle, line):
    """Finds the next line from a file."""
    for l in file_handle:
        l = l.strip()
        if l == line:
            return next(file_handle)


def main():
    username = input("Please enter the username you wish to see the password for: ")
    username = 'Username: ' + username
    with open('User_Details.txt') as read_file:
        password = find_next_line(read_file, username)
    password = password[len('Password: '):]
    print("Password '{0}' found for username '{1}'".format(password, username))

if __name__ == '__main__':
    main()

Finally, it's absolutely insane to store anything in this format (not to mention password security stuff, but I get you're just learning stuff), why not do something like:

username:password
markus:MarkusIsHappy123
BOB:BOB'S PASSWORD

This could then easily be converted into a dict:

with open('User_Details.txt') as read_file:
    user_details = dict(line.strip().split(':') for line in read_file)

And now to get a password for an username, you'd do:

username = input('Username: ')
if username in user_details:
    print('Password:', user_details[username])
else:
    print('Unknown user')
Community
  • 1
  • 1
Markus Meskanen
  • 19,939
  • 18
  • 80
  • 119
  • Could you put this into one code block please, note that security isnt an issue with this project – b4sh Oct 17 '15 at 22:12
  • @NodeMN So you're asking me if I can do the whole program for you? I can help, but SO is not a code writing service. Besides, I already did write you the code, you should be able to do the rest... – Markus Meskanen Oct 17 '15 at 22:16
  • @NodeMN Is there something in particular that you didn't understand? – Markus Meskanen Oct 17 '15 at 22:17
  • No its just knowing what order to put it in. Im new at python. – b4sh Oct 17 '15 at 22:18
  • ValueError: dictionary update sequence element #2 has length 1; 2 is required – b4sh Oct 17 '15 at 22:24
  • @NodeMN The last piece of code only works if you update your user file to match the one I suggested. One of your lines does *not* contain a colon (`:`) – Markus Meskanen Oct 17 '15 at 22:27
  • Im so sorry and really appreciate your help but are you talking about a my text document not containing a colon or someone else in my code. – b4sh Oct 17 '15 at 22:30
  • @NodeMN Your text document. – Markus Meskanen Oct 17 '15 at 22:31
  • @NodeMN I think you need to study my answer a little more, you're not supposed to use the last two/three code blocks. – Markus Meskanen Oct 17 '15 at 22:35
  • password = password[len('Password: '):] TypeError: 'NoneType' object is not subscriptable – b4sh Oct 17 '15 at 22:47
  • @NodeMN That means you've entered an incorrect username. – Markus Meskanen Oct 17 '15 at 22:50
  • I got it working perfectly but how would I print that there were no matches found and give them a ask them again? – b4sh Oct 17 '15 at 23:18
  • @NodeMN Why don't you fugure out that by yourself? You're already using a `while` loop in your original post. And a simple `if password is None:` should do – Markus Meskanen Oct 17 '15 at 23:20
  • Ive tried loads of different things and all I seem to get is password = password[len('Password: '):] TypeError: 'NoneType' object is not subscriptable. Do you have any hints to help? – b4sh Oct 18 '15 at 00:28
  • @NodeMN Sorry I was asleep. Seems like you've already accepted my answer, so hopefully you figured it out yourself. Regardless, `password = password[len('Password: '):]` only works if `password` is a string, so you have to explicitly make sure that `password = find_next_line(read_file, username)` doesn't set `password` to `None`, and if it does, you have to ask the user for a new input cause that username was not found. – Markus Meskanen Oct 18 '15 at 12:51