Writing multiple lines to file and then reading them with Python - 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.

Related

PYTHON: IF statement with Parameters from a file not working correctly

I am creating a program that the user can set the odds of a good roll. The variable is stored in a file so that it can be used even when you close the program. My problem is that only the first state of the if statement gets executed and I cannot figure out why.
file = open("rolltype.txt", "r")
user = input("Enter what you want to roll[e.x: 2d8]: ")
if file.readline() == "1":
print("Favor")
favor(user)
elif file.readline() == "2":
print("AGAINST")
against(user)
elif file.readline() == "3" or file.readline() == None:
print("NEUTRAL")
check(user)
file.close()
I open the file in read mode and in the if statement I check 4 possible scenarios, and call the appropriate function.
If the file contains the value 1 then the program executes correctly, and if not, the elifs get jumped over.
Side-note: the print() inside the if are used for debugging.
Thank you for taking the time to read and maybe try to help. Have a great rest of the day!
There are two problems with your code.
readline() on a file includes the newline at the end of the line. It will never match "1" or any other string that doesn't end with a newline.
You're comparing a different line each time because of the multiple calls to readline(). Every time readline() is executed, the pointer is moved to the next line. If the file doesn't contain enough lines, some of them are going to return the empty string, and it won't match anything either.
Solution: call readline() once into a variable and use strip() to take off the newline (and any other whitespace).
num_from_file = readline().strip()
if num_from_file == "1":
Every time you call file.readline(), it is reading the next line in the file.
Therefore, you will get a different result for every conditional expression.
In order to solve this, you should simply store the value in a variable and check that in your conditional expressions:
user = input("Enter what you want to roll[e.x: 2d8]: ")
value = file.readline()
if value == "1":
print("Favor")
favor(user)
elif value == "2":
print("AGAINST")
against(user)
elif value == "3" or value == None:
print("NEUTRAL")
check(user)
file.close()
Every time you call file.readline() it reads a new line from the file. This can be fixed by assigning it to a variable before the if statements.
line = file.readline()
if line == "1":
print("Favor")
elif line == "2":
print("Against")
elif line == "3":
print("Nuetral")
However, I don't think that readline always trims trailing whitespace. Therefore, I suggest using file.readline().strip().
I am not sure I understand your problem, but I already encounter something similar. It was because the use of readline() multiple times.
Can't you just use :
fileContent = file.readline()
user = input("Enter what you want to roll[e.x: 2d8]: ")
if fileContent == "1":
print("Favor")
favor(user)
elif fileContent == "2":
print("AGAINST")
against(user)
elif fileContent == "3" or fileContent == None:
print("NEUTRAL")
check(user)
file.close()
I am not sure about my answer because I don't understand how your file is written.
You can simplify your code by using dictionaries to define a value to print mapping print_dct , and value to function mapping func_dct
Also you can use with to open your file, so that you would not need to close it explicitly.
user = input("Enter what you want to roll[e.x: 2d8]: ")
print_dct = {"1": "Favor", "2": "AGAINST", "3": "NEUTRAL"}
func_dct = {"1": favor, "2": against, "3": user}
with open("rolltype.txt", "r") as file:
value = file.readline()
if value == None:
print(print_dct['3'])
check(user)
elif value in print_dct:
print(print_dct[value])
func_dct[value](user)

Python Iteration Mess

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.

In Python, how do you scan for a specific number

Hello I am making a game out of python, and I made the game write data on a text document, and is there a way I can code so if the text file says a person named Bob is on level 4, then make the program start on level 4. I have tried using for loop to do the job, but it wont work. It will not initiate the text file and just goes over to level 1.
Here is the game code(for reading and writing:
import os
#---------------------------
os.system("color a")
#---------------------------
def ping(num):
os.system("ping localhost -i", num, ">nul")
def cls():
os.system("cls")
#--------------------------
print("the game")
ping(2)
cls()
print("1: New Game")
print("2: Continue")
print("3: Credits")
while True:
choice=input("Enter")
if choice==1:
name=input("Enter your name")
firstsave=open("data.txt", "W")
firstsave.write(name, " ")
# there will be the game data here
elif choice==2:
opendata=file("data")
#opening the file
while True:
''' is the place where the file scanning part needs to come.
after that, using if and elif to decide which level to start from.(there are a total of 15 levels in the game)
'''
The text file:
User Level
Bob 5
George 12
You haven't given quite enough information, but here's one approach:
elif choice == 2:
with open("x.txt") as f:
f.readline() # skip the first line
for lines in f: # loop through the rest of the lines
name, level = line.split() # split each line into two variables
if name == playername: # assumes your player has entered their name
playlevel(int(level)) # alternatively: setlevel = level or something
break # assumes you don't need to read more lines
This assumes several things, like that you know the player name, and that the player has only one line, the name is just a single word, etc. Gets more complicated if things are different, but that's what reading the Python documentation and experimenting is for.
Also note that you use 'w' to write in choice 1, which will (over)write rather than append. Not sure if you meant it, but you also use different filenames for choice 1 and 2.

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())

Saving/Loading lists in Python

I am new to python (and programming in general) and am making a database/register for a typical class. I wanted the user to be able to add and remove pupils from the database, I used lists primarily for this but have hit a stump.
Whenever I restart the program the list the user has modified returns back to the defualt list I specified in the code. I looked around the internet and tried to save the list onto a seperate txt file. However the txt file also goes back to the defualt every time I restart the program. I would like you to please give me a way to save the changes made to the list and keep them that way. Here is the code (it's not very good):
def menu():
print "*****************CLASS REGISTER*****************"
print "Press 1 See The List Of Pupils"
print "Press 2 To Add New Pupils"
print "Press 3 To Remove Pupils"
print "Press 0 To Quit \n"
filename = open('pupil.txt','r')
pupil = ["James Steele", "Blain Krontick", "Leeroy Jenkins", "Tanvir Choudrey"]
def see_list(x):
print x
def add_pupil(x):
print "You have chosen to add a new pupil.\n"
option = raw_input("Please type the childs name.")
x.append(option)
filename = open('pupil.txt','w')
filename.write('\n'.join(pupil))
filename.close()
print option, "has been added to the system."
return x
def delete_pupil(x):
print "You have chosen to remove a pupil.\n"
option = raw_input("Please type the childs name.")
if option in x:
x.remove(option)
filename = open('pupil.txt','w')
filename.write('\n'.join(pupil))
filename.close()
print option, "has been removed from the system."
else:
print "That person is not in the system."
return x
one = 1
while one != 0:
menu()
option = input()
if option == 1:
see_list(pupil)
elif option == 2:
add_pupil(pupil)
elif option == 3:
delete_pupil(pupil)
elif option == 0:
break
else:
print "That is not a valible choice."
filename = open('pupil.txt','w')
filename.write('\n'.join(pupil))
filename.close()
if option == 0:
quit
Well, you just open the pupil.txt file but never read back its contents. You need something like this:
filename = open('pupil.txt', 'r')
contents = filename.read()
filename.close()
pupil = [name for name in contents.split('\n') if name]
Also, you will need to handle the case when the pupil.txt file does not exist; this can be done with a try..except block around the IO calls.
Finally, as one of the comments has mentioned above, have a look at the pickle module, which lets you store a Python object in a file in Python's internal format (which is not really readable, but saves you a lot of hassle).
Not related to your question directly, but this:
one = 1
while one != 0:
...
is silly. All you need is:
while True:
...
This is what a database is for. Use sqlite - a simple file-based database the libraries for which come bundled with python.

Categories

Resources