Python Iteration Mess - python

As you can see below I am trying to make a program that takes a file called names.txt, breaks it down into a list with .split('/n'), then adds a password for each user in the list. For some reason the for look treats the list as if it were a string, so instead of treating it like:
Bob
Charley
Ron
It breaks it down like:
B
o
b
C
h
....
Thus giving each letter a password instead of the list itself.
What am I doing wrong?
Is there a way I can test to see what the for loop is actually being given?
I have been playing with it to see if it were being given a string, but the list appears to be clealy a list when printed, so why would it be getting treated like a string in the for loop?
def importNames():
try:
file = open("names.txt", "r")
contents = file.read()
print(contents)
file.close()
return contents
except:
print("The file was not found.")
print("Make sure you have a file called \"names.txt\" in the working directory (where you ran this program)")
exit()
def createPasswordList(nameList):
print("They are being given the standard password of \"p#ssw0rd.\"")
#nameList = ["Pickles", "Bob's", 'wow zers john'] #This is for testing purposes. It works just fine, but the original nameList breaks down badly.
passList = []
#for x, value in enumerate(nameList):
for i in nameList:
print(i)
passList.append("p#ssw0rd")
print(passList)
return passList
def createUsers(nameList, passwordList): #takes in a list of usernames, then adds creates them.
for i in nameList:
print("This will do something soon.")
#encPass = crypt.crypt(passwordList[i],"22") #22 is a salt number, use crypt per useradd manual
#os.system("useradd -p " + encPass + " " + nameList[i]) #useradd -p encryptedpass username
def convertNamesToList(originalList):
print("Converting names.") #Use newline as a delimiter
newList = originalList.split('\n')
print(newList)
return newList
def convertNameToUsernames(originalNames):
print("Creating usernames")
print("This program is used to make some users.")
print("If you import a file, have it in the working directory called \"names.txt\".")
print("Would you like to import names or add them manually? (n/m)")
answer = input()
if (answer is 'm' or answer is 'M'):
createUser()
print("The user gets created. Good job.")
else:
originalNames = importNames() #this will return a string of the file.
convertNamesToList(originalNames) #convert the string to sets of names. Use newlines as delimiters.
#convert the names to usernames
print("Do the users have passwords? (y/n)")
#answer = input()
answer = 'n' ###FORCE###
if (answer is 'n' or answer is 'N'):
passwordList = createPasswordList(originalNames)

You're never doing anything with the return value from convertNamesToList. You don't store it anywhere. Then you pass originalNames, which is a string (you even indicate this in a comment) to createPasswordList.
I think you want something like:
originalNames = importNames() #this will return a string of the file.
listOfNames = convertNamesToList(originalNames) #convert the string to sets of names. Use newlines as delimiters.
#convert the names to usernames
print("Do the users have passwords? (y/n)")
#answer = input()
answer = 'n' ###FORCE###
if (answer is 'n' or answer is 'N'):
passwordList = createPasswordList(listOfNames)

It looks like your nameList is actually a string. Assuming that you have one name per line of the names.txt file, Try this:
def importNames():
try:
file = open("names.txt", "r")
contents=[]
for line in file.read():
contents.append(line)
print(contents)
file.close()
return contents
You then no not need to convert it to a list later.

Related

Writing into a file Python

I am trying to get user input into a text file on different lines. The user input is stored in a list then the list is appended. I realize you are not suppose to use quotes since that will act as your own input. How could I go about using the user input?
def userfile():
text = []
s1 = input("Enter sentence #1 ")
s1 = input("Enter sentence #2 ")
text.append(s1)
userfile = open(os.path.join(sys.path[0], "sample2.txt"), "w")
lines = ['s1\n', 's1\n']
userfile.writelines(lines)
userfile.close()
newfile = open(os.path.join(sys.path[0],"sample2.txt"), "r")
print(newfile.read())
def main():
#txtfile()
userfile()
if __name__ == "__main__":
main()
I think your error is in userfile(): you write both inputs into the same variable s1. And then you don't even use the text array you just created.
Try this:
def userfile():
text = []
text.append(input("Enter sentence #1 "))
text.append(input("Enter sentence #2 "))
# ...
userfile.writelines(text)
# ...
I think you should just modify your code to lines = [s1+'\n', s1+'\n'] if I Understand your problem.
First your indentation is wrong, and you are using a variable named userfile within a function called userfile() which is confusing but doesn't really matter, finally you are overwriting your s1 variable with the second input.
I also recommend using with when opening a file as that will automatically close the file when finished with it.
def userfile():
text = []
for i in range(1, 3):
text.append(input("Enter sentence #{i} ".format(i)))
with open(os.path.join(sys.path[0], "sample2.txt"), "w") as my_file:
my_file.writelines(text)
with open(os.path.join(sys.path[0],"sample2.txt"), "r") as new_file:
print(new_file.read())
def main():
# txtfile()
userfile()
if __name__ == "__main__":
main()
Also I used a loop for the user input which allows you to require as many inputs from the user as you want by only changing 1 number.

I cant get my code to open my .txt file and read if it has names in it

In my code, it asks what is your name and if your name is in the file then say welcome back then their name if their name is not in it then ask if they want for Cora to remember it if yes then write their name into the file.
def AI():
names = open("\\\\ph-fss1\\Students\\S39055\\Desktop\\names.txt","w")
name = raw_input("Hello and welcome to the Creative, Orginal, Reactive, A.I, Cora. What is your name? ")
file.read(names)
if name in names:
print "Welcome back " + name
if name not in names:
print "You are a new user would you like to me to remember your name?"
name_yes = raw_input("Yes/No: ").lower()
if name_yes == "yes":
file.wright(name)
file.close()
Lets take a look at a few improvements. Since you use raw_input() i'll assume Python 2.x:
def AI():
# you can use r'' to specify a raw string and avoid using '\\' to escape '\'
fpath = r'\\ph-fss1\Students\S39055\Desktop\names.txt'
# this is called a 'context manager'
# when you are done with your operations, the file will close automatically
# the 'r+' mode opens for reading and writing
with open(fpath, 'r+') as f:
# this is list comprehension and I assume each name is on a new line
# a set is a container for unique values
# assuming that you will not have multiple of the same names
# if so, how do you plan to account for them?
names = set([line for line in f])
print "Hello and welcome to the Creative, Orginal, Reactive, A.I, Cora."
name = raw_input("What is your name? ")
if name in names:
print "Welcome back " + name
else:
print "You are a new user, would you like to me to remember your name?"
# this is fine, but what happens I just put in 'y' or 'n'?
# look for methods to handle invalid input
choice = raw_input("Yes/No: ").lower()
if choice == "yes":
# because we opened the file in 'r+', we seek(0) which puts us at the top
# then when we writelines(list(names)) we overwrite the entire file
# and store the original data with the new name as well
file.seek(0)
names.add(name)
# writelines() just writes an iterable versus a string
file.writelines(list(names))
There are some design choices you have to make here. But if you have any questions, ask away.
The issue was that you never actual read the contents of the file in order to check if the name existed. Try this:
name = raw_input("Hello and welcome to the Creative, Orginal, Reactive, A.I, Cora. What is your name? ")
if name in open("\\\\ph-fss1\\Students\\S39055\\Desktop\\names.txt").read():
print "Welcome back " + name
else:
print "You are a new user would you like to me to remember your name?"
name_yes = raw_input("Yes/No: ").lower()
if name_yes == "yes":
with open("\\\\ph-fss1\\Students\\S39055\\Desktop\\names.txt", "a") as myfile:
myfile.write(name)

How do I allow only the latest inputs to be saved - Python

How do I implement a simple code that will only save the student's latest 3 scores? If the test is repeated later, the old score should be replaced.
Thank you.
This is the code that asks the user the questions and saves the results in the txt. files.
import random
import math
import operator as op
correct_answers = 0
def test():
num1 = random.randint(1, 10)
num2 = random.randint(1, 10)
ops = {
'+': op.add,
'-': op.sub,
'*': op.mul,
}
keys = list(ops.keys())
rand_key = random.choice(keys)
operation = ops[rand_key]
correct_result = operation(num1, num2)
print ("What is {} {} {}?".format(num1, rand_key, num2))
user_answer= int(input("Your answer: "))
if user_answer != correct_result:
print ("Incorrect. The right answer is {}".format(correct_result))
return False
else:
print("Correct!")
return True
username = input("What is your name? ")
print("Hi {}! Welcome to the Arithmetic quiz...".format(username))
class_name = input("Are you in class 1, 2 or 3? ")
correct_answers = 0
num_questions = 10
for i in range(num_questions):
if test():
correct_answers +=1
print("{}: You got {}/{} questions correct.".format(
username,
correct_answers,
num_questions,
))
class_name = class_name + ".txt" #creates a txt file called the class that the user entered earlier on in the quiz.
file = open(class_name , 'a') #These few lines open and then write the username and the marks of the student into the txt file.
name = (username)
file.write(str(username + " : " ))
file.write(str(correct_answers))
file.write('\n') #This puts each different entry on a different line.
file.close() #This closes the file once the infrmation has been written.
A much better solution would be to store the data in a different format that made everything easy. For example, if you used a shelve database that mapped each username to a deque of answers, the whole thing would be this simple:
with shelve.open(class_name) as db:
answers = db.get(username, collections.deque(maxlen=3))
answers.append(correct_answers)
db[username] = answers
But if you can't change the data format, and you need to just append new lines to the end of a human-readable text file, then the only want to find out if there are already 3 answers is to read through every line in the file to see how many are already there. For example:
past_answers = []
with open(class_name) as f:
for i, line in enumerate(f):
# rsplit(…,1) instead of split so users who call
# themselves 'I Rock : 99999' can't cheat the system
name, answers = line.rsplit(' : ', 1)
if name == username:
past_answers.append(i)
And if there were 3 past answers, you have to rewrite the file, skipping line #i. This is the really fun part; text files aren't random-access-editable, so the best you can do is either read it all into memory and write it back out, or copy it all to a temporary file and move it over the original. Like this:
excess_answers = set(past_answers[:-2])
if excess_answers:
with open(class_name) as fin, tempfile.NamedTemporaryFile() as fout:
for i, line in enumerate(fin):
if i not in excess_answers:
fout.write(line)
os.replace(fout.name, fin)
That part is untested. And it requires Python 3.3+; if you have an earlier version and are on Mac or Linux you can just use os.rename instead of replace, but if you're on Windows… you need to do some research, because it's ugly and no fun.
And now, you can finally just append the new answer, as you're already doing.

Writing multiple lines to file and then reading them with Python

I've just undertaken my first proper project with Python, a code snippet storing program.
To do this I need to first write, then read, multiple lines to a .txt file. I've done quite a bit of googling and found a few things about writing to the file (which didn't really work). What I have currently got working is a function that reads each line of a multiline input and writes it into a list before writing it into a file. I had thought that I would just be able to read that from the text file and add each line into a list then print each line separately using a while loop, which unfortunately didn't work.
After going and doing more research I decided to ask here. This is the code I have currently:
'''
Project created to store useful code snippets, prehaps one day it will evolve
into something goregous, but, for now it's just a simple archiver/library
'''
#!/usr/local/bin/python
import sys, os, curses
os.system("clear")
Menu ="""
#----------- Main Menu ---------#
# 1. Create or edit a snippet #
# 2. Read a snippet #
# 0. Quit #
#-------------------------------#
\n
"""
CreateMenu ="""
#-------------- Creation and deletion --------------#
# 1. Create a snippet #
# 2. Edit a snippet #
# 3. Delete a snippet (Will ask for validation) #
# 0. Go back #
#---------------------------------------------------#
\n
"""
ReadMenu="""
#------ Read a snippet ------#
# 1. Enter Snippet name #
# 2. List alphabetically #
# 3. Extra #
# 0. Go Back #
#----------------------------#
"""
def readFileLoop(usrChoice, directory):
count = 0
if usrChoice == 'y' or 'n':
if usrChoice == 'y':
f = open(directory, 'r')
text = f.read()
f.close()
length = len(text)
print text
print length
raw_input('Enter to continue')
readMenu()
f.close()
elif choice == 'n':
readMenu()
def raw_lines(prompt=''):
result = []
getmore = True
while getmore:
line = raw_input(prompt)
if len(line) > 0:
result.append(line)
else:
getmore = False
result = str(result)
result.replace('[','').replace(']','')
return result
def mainMenu():
os.system("clear")
print Menu
choice = ''
choice = raw_input('--: ')
createLoop = True
if choice == '1':
return creationMenu()
elif choice == '2':
readMenu()
elif choice == '0':
os.system("clear")
sys.exit(0)
def create():
os.system("clear")
name = raw_input("Enter the file name: ")
dire = ('shelf/'+name+'.txt')
if os.path.exists(dire):
while os.path.exists(dire):
os.system("clear")
print("This snippet already exists")
name = raw_input("Enter a different name: ")
dire = ('shelf/'+name+'.txt')
print("File created\n")
f = open(dire, "w")
print("---------Paste code below---------\n")
text = raw_lines()
raw_input('\nEnter to write to file')
f.writelines(text)
f.close()
raw_input('\nSnippet successfully filled, enter to continue')
else:
print("File created")
f = open(dire, "w")
print("---------Paste code below---------\n")
text = raw_lines()
print text
raw_input('\nEnter to write to file')
f.writelines(text)
f.close()
raw_input('\nSnippet successfully filled, enter to continue')
def readMenu():
os.system("clear")
name = ''
dire = ''
print ReadMenu
choice = raw_input('--:')
if choice == '1':
os.system("clear")
name = raw_input ('Enter Snippet name: ')
dire = ('shelf/'+name+'.txt')
if os.path.exists(dire):
choice = ''
choice = raw_input('The Snippet exists! Open? (y/n)')
'''if not choice == 'y' or 'n':
while (choice != 'y') or (choice != 'n'):
choice = raw_input('Enter \'y\' or \'n\' to continue: ')
if choice == 'y' or 'n':
break'''
readFileLoop(choice, dire)
else:
raw_input('No snippet with that name exists. Enter to continue: ') #add options to retry, create snippet or go back
readMenu()
elif choice == '0':
os.system("clear")
print Menu
def creationMenu(): ###### Menu to create, edit and delete a snippet ######
os.system("clear")
print CreateMenu
choice = raw_input('--: ')
if choice == '1': ### Create a snippet
os.system("clear")
print create()
print creationMenu()
elif choice == '2':
os.system("clear") ### Edit a snippet
print ("teh editon staton")
raw_input()
print creationMenu()
elif choice == '3':
os.system("clear") ### Delete a snippet
print ("Deletion staton")
raw_input()
print creationMenu()
elif choice == '0': ### Go Back
os.system("clear")
######## Main loop #######
running = True
print ('Welcome to the code library, please don\'t disturb other readers!\n\n')
while running:
mainMenu()
######## Main loop #######
Tl;Dr: Need to write and read multiline text files
The problem that I'm having is the way the multilines are being stored to the file, it's stored in list format e.g ['line1', 'line2', 'line3'] which is making it difficult to read as multilines because I can't get it to be read as a list, when I tried it added the whole stored string into one list item. I don't know if I'm writing to the file correctly.
OK, so the problem is with writing the file. You're reading it in correctly, it just doesn't have the data you want. And the problem is in your raw_lines function. First it assembles a list of lines in the result variable, which is good. Then it does this:
result = str(result)
result.replace('[','').replace(']','')
There are two small problems and one big one here.
First, replace:
Return[s] a copy of the string with all occurrences of substring old replaced by new.
Python strings are immutable. None of their methods change them in-place; all of them return a new string instead. You're not doing anything with that new string, so that line has no effect.
Second, if you want to join a sequence of strings into a string, you don't do that by calling str on the sequence and then trying to parse it. That's what the join method is for. For example, if your lines already end with newlines, you want ''.join(result). If not, you want something like '\n'.join(result) + '\n'. What you're doing has all kinds of problems—you forgot to remove the extra commas, you will remove any brackets (or commas, once you fix that) within the strings themselves, etc.
Finally, you shouldn't be doing this in the first place. You want to return something that can be passed to writelines, which:
Write[s] a sequence of strings to the file. The sequence can be any iterable object producing strings, typically a list of strings.
You have a list of strings, which is exactly what writelines wants. Don't try to join them up into one string. If you do, it will run, but it won't do the right thing (because a string is, itself, a sequence of 1-character strings).
So, if you just remove those two lines entirely, your code will almost work.
But there's one last problem: raw_input:
… reads a line from input, converts it to a string (stripping a trailing newline), and returns that.
But writelines:
… does not add line separators.
So, you'll end up with all of your lines concatenated together. You need the newlines, but raw_input throws them away. So, you have to add them back on. You can fix this with a simple one-line change:
result.append(line + '\n')
To read multiple lines from a file, it's easiest to use readlines(), which will return a list of all lines in the file. To read the file use:
with open(directory, 'r') as f:
lines = f.readlines()
And to write out your changes, use:
with open(directory, 'w') as f:
f.writelines(lines)
fileList = [line for line in open("file.txt")]
While the previously mention idiom will work for reading files, I like mine. Its short and to the point.

store each word from a text file into a list

So I'm trying to make a program that reads a file, and stores each word into a list of strings. I can add each line into a list of strings, (see the code below) but how do I add each individual word into a list of strings?
Also, since this is a Mad Libs program, I'll have some phrases that will look like, noun, or body part. How would I store body part into the list as one string, since it is technically two separate words?
Code for reference:
def main():
file_list = []
while True: #while loop that runs until the user puts in a file name...
#or types in quit
#asks the user for a file name, or gives them an option to quit
file_name = raw_input("Enter in the name of the file, or type in quit to quit: ")
if file_name == "quit":
sys.exit(0) #quits the program
else:
try: #attempts to open the file
fin = open(file_name)
break
except: #prints out if file name doesn't exist
print "No, no, file no here."
for eachLine in fin: #strips out the new lines from the file
file_list.append(eachLine.strip())
print file_list
if __name__ == '__main__':
main()
file_list.extend(eachLine.split())

Categories

Resources