append text from input without changing previous text in python - python

i want to make python create a file if it doesn't exist ,then take text from users input and append into my file and to be able to use my code several times without changing text before it
def register():
f=open('1.txt','w')
f=open('1.txt','r')
users=f.readlines()
f=open('1.txt','a')
while True:
username = input('Enter your username: ')
password = input('Enter your password: ')
if username in users:
print('this username is taken')
else:
f.write(f'{username}\n')
f.write(f'{password}')
break
this is my code

EAFP approach (which is more pythonic that LBYL):
try to create a file
handle specific exception if it exists
either way do your logic in finally block
try:
with open("1.txt","x") as f: pass
except FileExistsError:
print("File already exists!")
finally:
with open("1.txt", "r+") as f:
lines = f.readlines()
username, password = input("Type username and password (separated by a space): ").split()
if f"{username}\n" in lines:
print('This username is taken!')
else:
f.writelines([f"{username}\n",f"{password}\n"])
Keep in mind though that:
if the username and password are the same this won't work correctly (or at least not as expected imho, as homework figure out why :D )
passwords in general should NOT be kept as plain text
you should add the "boilerplate" if __name__=="__main__": thingy if it's a standalone and no part of a function/class etc
you could wrap the input in try...except ValueError block to be extra safe when somebody enters a single value or three values and so on
Comments:
If you do something like this:
f=open('1.txt','w')
f=open('1.txt','r')
The 2nd line shadows the first one, so it makes no sense, it's the same as:
x=2
x=3
print(x)
The 1st assignment is "dead"
Most often you want to use with when handling files operations, otherwise it's your responsibility to close the file as well.

Related

How to write and read from different lines in a text file?

I have a very simple 'login' program that I've almost got finished. I'm trying to get my make_acc() function to write the username on line 1 and the password on line 2, as well as make my login() function read those separate lines per what needs to be checked. I'm pretty sure the answer has to do with marking the readline command for which line needs to be read, but I'm not sure how to implement it in my code properly. Here's the code.
# This function has the user input a username for their account
def make_acc():
username = input('Make a username:')
file = open('acc_data.txt','w')
file.write(username)
file.close()
#password = input('Make a password:')
#file = open('acc_data.txt','w')
#file.write(password)
# This function has the user login to a preexisting account
def login():
input_user = input('Enter your username:')
file = open('acc_data.txt','r')
username = file.readline()
if input_user == username:
print('You are now logged in')
else:
print('That user does not exist')
login()
# This variable will be defined as a yes or no depending on whether or not the use has an account
acc_bool = input('Do you already have an account?:')
# This if statement runs the login() function if the user answered yes to the previous input
if acc_bool == 'yes':
login()
# This elif statement runs the make_acc() function if the user answered no to the previous input
elif acc_bool == 'no':
make_acc()
login()
This should do it:
def make_acc():
username = input('Make a username:')
password = input('Make a password:')
with open('acc_data.txt','a') as file:
file.write(username+'\n')
file.write(password)
def login():
input_user = input('Enter your username:')
with open('acc_data.txt','r') as file:
if input_user in [u for i,u in enumerate(file.readlines()) if not u%2]:
print('You are now logged in')
else:
print('That user does not exist')
login()
Instead of having the usernames and passwords all in 2 lines, you can use indexes to determine whether a line is a username or password: even indexes are for usernames, and odd ones are for passwords.
UPDATE:
This part: [u for i,u in enumerate(file.readlines()) if not u%2] lists all the strings in file.readlines() (a list of all the lines in f.read()) if the index of the string, i, doesn't leave a remainder when divided by 2.
You see, enumerate() will basically let us iterate through an array and let use easily access the index of the current iteration.
First, uncomment the part of make_acc that asks for a password and add a file.close().
Then, notice that when you've run the program and inputted the two pieces of information, only one is left in the file, this is because, when calling open(), you use the
w mode, which truncates the file before allowing you to write. The consequence of this is that when you open the file again a couple of lines later, all information previously stored is lost. The solution is to use mode r+ or a or just not close the file until the end of the function, thereby avoiding having to reopening it when writing the password.
Next, when reading from the file, you can use file.readline() just as you already are doing. Choosing what line to read happens by default, because every call to readline advances what line is being read. This means that the second time you call it since you opened the file, the second line will be read.

Checking if a string is in a file

I am making a program that checks to see if any of the user's input is in the file. If the user input is not currently in the file, then we will append that input into the used_passwords file and ask the user to type something else again. else if they retype the input we just recently added(or any of the presets) then we want to tell them that they can't reuse a password.
The problem I am having with this code is that whenever I type a letter that is from the word in the used_passwords file or if I type a part of the word in the file then the program tells me that I can't reuse a password.
For example: If I type in "abc", the program will tell me that I have already reused that password and I am assuming it is probably because the program reads the files character by character and reads the abc in abcdeF!23.
Although, I don't want the program to tell me I can't reuse a or multiple characters from the file. I want the program to tell me that I can't reuse a word from the program
I am also wondering if we could put the inputs or presets into an array IN THE FILE.
fileUsed_Pass = open("used_passwords.txt", 'a')
fileUsed_Pass.write("\nabcdeF!23")
fileUsed_Pass.write("\n\n")
fileUsed_Pass.write("zxcbhK#44")
fileUsed_Pass.write("\n\n")
fileUsed_Pass.write("poiuyT&11")
fileUsed_Pass.write("\n\n")
fileUsed_Pass.close()
def password():
string = input("Enter Here:")
if string in open('used_passwords.txt').read():
print("You can not reuse that password!\n")
password()
else:
# file-append.py
f = open('used_passwords.txt','a')
f.write('\n'+string)
f.close()
password()
password()
UPDATE: I have gotten the code to work using the with statement.
rather than using an If and else statement, I had used a with statement.
Here what I am doing is checking for every single line to see if it has any text that matches my input string. If there are none, then we'll make some_variable equal True. If it doesn't, then we'll make it equal false.
with open("used_passwords.txt", 'r') as tFile:
for line in tFile:
if string != line and string+"\n" != line:
some_variable = True
else: #If it equals anything else from the file, then false
some_variable = False
break
#print(some_variable)
#this was added for me/the user to make sure that the with statement was working
Afterwards, if it does equal True: we'll add it to the file. If it doesn't we'll make the user input another password that does not match any of the ones insie of the file.
tFile = open("used_passwords.txt", 'a')
if some_variable == True:
tFile.write("\n" + string)
print("\nGOOD! Password does not match old ones!")
elif some_variable == False:
print("\nYou can not re-use a password!")
password()
Working directly with text files is probably not the greatest solution;
you should consider using some form of database instead (such as the sqlite3 library which, IIRC, comes preinstalled with Python3).
Also, keep in mind that storing passwords as clear text is a security "no-no".
At the very least, use one of the many available cryptographic hash functions, then store and compare the hashes, not the passwords.
Here's a basic example that uses both sqlite3 and SHA-256, a common hashing function:
#!/usr/bin/python3
import sqlite3
import hashlib
db = sqlite3.connect( "used_passwords.db" )
cur = db.cursor()
cur.execute( "CREATE TABLE IF NOT EXISTS passwords( pwd TEXT, UNIQUE( pwd ))" )
def password():
pwd = input( "password: " )
sha = hashlib.sha256( pwd.encode( 'utf-8' )).hexdigest()
cur.execute( "INSERT INTO passwords VALUES( ? )", ( sha, ))
while True:
try:
password()
break
except KeyboardInterrupt:
print( "aborted" )
break
except sqlite3.IntegrityError:
print( "cannot reuse that password" )
db.commit()
db.close()
Note the UNIQUE constraint on pwd, which ensures that an sqlite3.IntegrityError exception is raised whenever a password is already present in passwords (this makes the verification implicit, and minimizes the SQL cumbersomeness).
Usage example:
% ./pwd.py
password: foo
% ./pwd.py
password: foo
cannot reuse that password
password: bar
%
You can verify that no clear-text password appears in the database:
% sqlite3 ./used_passwords.db
SQLite version 3.16.2 2017-01-06 16:32:41
Enter ".help" for usage hints.
sqlite> select * from passwords;
2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae ; <- this is "foo"
fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 ; <- this is "bar"
sqlite>
Of course you can expand on that and add more features, such as support for multiple users, password expiration, etc...
Considering that you are adding a \n after each password you enter in the file, you can try to append \n to the string variable and then search after that.
You're using .read(), which reads the entire file as one string.
word = 'abc'
for line in open('file.txt').readlines():
if word in line:
return True
Use .readlines() instead and loop through every line to check if the string is in any of the file lines.

Checking file for text that matches input

I have a program that needs a username system, I want the user to enter their username and the program checks the file 'username' to see if it is in the list. My code below works if there is only one person in the list, otherwise it prints correct and incorrect. How would I change my code so if just one line matches the input it prints correct.
username = input("enter username: ")
search = open("username", "r")
for line in search:
if username in line:
print ("correct")
else:
print ("incorrect")
You could exploit the for...else construct that python has.
with open("username") as f:
for line in f:
if username in line:
print("correct")
break
else:
print("incorrect")
The else block is run if the program exited naturally - without breaking out from the loop.
If you do not like traditional for loops, then I suggest you this solution:
with open("username") as f:
isInList = [username in line for line in f]:
if any(isInList):
print ("correct")
else:
print("incorrect")
One way of achieving this is to simply return after it finds a match. Using return and encapsulating the logic into a function would allow you to do other things with result. Also, I would suggest using the with statement for opening files as it has better error handling and automatically takes care of closing the file and cleanup. Here is a short tutorial on the with statement.
username = input("enter username: ")
def read_file():
with open("username", "r") as f:
for line in f:
if username in line:
return "correct"
else:
return "incorrect"
result = read_file()
print(result)
# Or do whatever else you want with the result

if not working for nth line in document

I wanted to make a simple login system with python 3.5. what it does is opens a document with usernames and passwords inside it. the document has a username on the first line, and the password for that user on the second line. this continues through the document, resulting in usernames on every odd line, and passwords on every even line. the loop goes through all 20 lines (for 10 users) and takes every odd line as a username, and every even line as a password. it goes through, and checks if the username and password are correct. for some reason, it does not work, it just asks to input username, and input password, and doesnt return anything. it is opening the document fine, as it works when i print out the usernames and passwords.
username = input('please enter your username')
password = input('please unter your password')
for i in range(0,20,2):
text_file = open('users.txt','r')
database = text_file.readlines()
if username == database[i] and password == database[i+1]:
print('login accepted')
else:
if username == database[i] and password != database[i+1]:
print('incorrect password')
text_file.close()
The likely problem has more to do with string stripping than anything. Chances are you have a text file like:
myusername
mypassword
otherusername
otherpassword
and when you're reading it you get:
["myusername\n", "mypassword\n", ... ]
You can most likely fix this just by using str.strip on each line read from the file.
However you have a couple more logic errors than this. Here's one:
for i in range(0, 20, 2):
text_file = open(...)
database = text_file.readlines()
# you really want to open the file and read from it EVERY SINGLE LOOP??
and also:
if username == database[i] or password == database[i+1]:
# log in if your password is ANYONE'S password, or if your username
# is ANYONE'S username.
In the grand scheme of things, you should be pre-processing the text file to create a dictionary of key-value pairs.
database = {} # empty dict
with open('path/to/textfile.txt') as inf:
while True:
try:
username = next(inf)
password = next(inf)
except StopIteration:
break
else:
database[username.strip()] = password.strip()
username_in = input("What's your username? ")
password_in = input("What's your password? ")
if database[username_in] == password_in:
# login successful
But REALLY, you should never ever ever ever be storing passwords in plain text for any reason whatsoever. Good lord, man, do some research on password storage! :)
Answer by Adam Smith is great.
I can only add that the line
if database[username_in] == password_in:
might cause a KeyError if there is no such username in your database. You might want to either check if username exists in database before checking passwords or wrap password check in the try except block or use dict.get(key, default) method to get the password from your database
Here some code:
# Pre check
if username_in in database.keys():
if database[username_in] == password_in:
# ...
else:
# No such username in database
# try .. except
try:
if database[username_in] == password_in:
# ...
except KeyError:
# No such username in database
# get with default
# if no default is specified, default is None
if database.get(username_in) == password_in:

txt file to dictionary and login implementation Python 3

I am attempting to create a login script. I have the usernames and passwords in a text file that I want python to read and check through to find usernames and passwords.
The biggest problem I am having is "attaching" the password to a username. I can currently only scan the whole of the document for both but not necessarily attached to each other.
#-------------------------------------------------------------------------------
# Name: LogIn
# Purpose: Logging In
#
# Author: Dark Ariel7
#
# Created: 19/02/2013
# Copyright: (c) Dark Ariel7 2013
# Licence: I take no responsability for anything.
#-------------------------------------------------------------------------------
from getpass import getpass
from time import sleep
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
Username = ("")
Password = ()
def LogIn():
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
Data = (Database.read())
Username = ("")
Password = ()
Username = input("Username: ")
Password = getpass(str("Password: "))
LogIn= ",".join((Username,Password))
if LogIn in Data:
print("Welcome, " + Username)
sleep(3)
pass
else:
print("Failed, Sucker!")
sleep(5)
exit()
LogIn()
If you guys could help me figure out what exactly .join part is for that would be great. Should i make a dictionary and use the index for a login sheet? I also want some general feedback on how to make the code better.
This is the txt file that it will be reading:
[Dark Ariel7,123456]
[Poop,Anko]
*Edit Sorry guys I forgot to mention that I am using python 3 not 2. Thanks so far. Very quick replies. Also after the last else instead of exit what do I put so that the function loops until I get the right username password combo?
The ".join" part joins the username and password that the user types in with a comma between them (i.e. Poop,Anko) because that's the format in which it's stored in the database, so you can search for it that way.
Here's your code, edited up a bit, with some comments about functionality and style.
from getpass import getpass
from time import sleep
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
# These next two lines aren't necessary - these variables are never used; you may want to read up about namespaces: http://bytebaker.com/2008/07/30/python-namespaces/
#Username = ("")
#Password = ()
def LogIn():
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
# Removed the parentheses; they have no effect here. Putting parens around lone statements doesn't have any effect in python.
Data = Database.read()
# These next two lines are pointless, because you subsequently overwrite the values you give these variables. It looks like you're trying to "declare" variables, as you would in Java, but this isn't necessary in python.
# Username = ("")
# Password = ()
# Changed this from "input" to "raw_input" because input does something else that you don't want.
Username = raw_input("Username: ")
Password = getpass(str("Password: "))
LogIn= ",".join((Username,Password))
if LogIn in Data:
print("Welcome, " + Username)
# Not sure why you want the script to sleep, but I assume you have your reasons?
sleep(3)
# no need to pass
# pass
else:
print("Failed, Sucker!")
sleep(5)
# exit() isn't necessary - the function will end by itself.
# exit()
LogIn()
The basic problem you have is that your file has [ ] surrounding the username and password combination, but you fail to account for this.
There are some other stylistic issues with your code, here is an edited version:
import getpass
from time import sleep
password_file = r'C:\....\Database.txt'
def login(user,passwd):
''' Checks the credentials of a user '''
with open(password_file) as f:
for line in f:
if line.strip(): # skips blank lines
username,password = line.split(',') # this gets the individual parts
username = username[1:] # gets rid of the [
password = password[:-1] # the same for the password
if user == username and password == passwd:
return True
return False
if __name__ == '__main__':
username = input('Please enter the username: ')
passwd = getpass('Please enter the password: ')
if login(user,passwd):
print('Welcome {1}'.format(user))
sleep(3)
else:
print('Failed! Mwahahaha!!')
sleep(5)
To start off with, you don't need () to "initialize" variables; more to the point in Python you don't need to initialize variables at all. This is because Python doesn't have variables; but rather names that point to things.
Next, the python style guide says that variable names should be lowercase, along with method names.
Now - the main part of the code:
>>> username, password = '[username,sekret]'.split(',')
>>> username
'[username'
>>> password
'sekret]'
I used split() to break up the line into the username and password parts; but as you see there is still the [ messing things up. Next I did this:
>>> username[1:]
'username'
>>> password[:-1]
'sekret'
This uses the slice notation to strip of the leading and ending characters, getting rid of the [ ].
These lines:
with open(password_file) as f: # 1
for line in f: # 2
if line.strip(): # skips blank lines
Do the following:
Opens the file and assigns it to the variable f (see more on the with statement)
This for loop steps through each line in f and assigns the name line to each line from the file.
The third part makes sure we skip blank lines. strip() will remove all non-printable characters; so if there are no characters left, the line is blank and will have a 0 length. Since if loops only work when the condition is true, and 0 is a false value - in effect what happens is we only operate on non-blank lines.
The final part of the code is another if statement. This is a check to make sure that the file will run when you execute it from the command prompt.

Categories

Resources