How do I create a text file that contain a list of results in python - python

I am studying JavaScript and Python at the moment, and I am reading and writing to text files in Python at the moment. Currently, I am trying to: write a program that should, when instructed to do so, create a file, that contains a list of students that need to re-sit and the number of marks they need to score to get a minimum of 85.
I have already written code that displays whether or not a student has hit the minimum score of 85, and if they haven't, how many more marks they need. But now I'm stuck. Any help would be very greatly appreciated, thanks!
Python:
def menu():
target = 85
with open('homework.txt','r') as a_file:
for l in a_file:
name, number = l.split(',')
number = int(number)
print(name + ': ' + ('passed' if number>=target else str(target - number)))
input()
Text File:
emma smith,79
noah jones,32
olivia williams,26
liam taylor,91
sophia green,80
mason brown,98

You just need to open a file to write the prints:
def menu():
target = 85
results = open("results.txt",'w')
with open('homework.txt','r') as a_file:
for l in a_file:
name, number = l.split(',')
number = int(number)
results.write(name + ': ' + ('passed' if number>=target else str(target - number)) + '\n')
input()

It sounds like you just want to pipe the results of your program into another textfile.
python file.py > results.txt should do the trick.
(I didn't check your algorithm, as you mention that it's doing what you want it to do already)

I guess this might do what you need ...
def menu():
out_file = open("results.txt", "w")
target = 85
with open("homework.txt", "r") as a_file:
for l in a_file:
name, number = l.split(",")
number = int(number)
out_file.write("{},{}\n".format(name, ('passed' if number>=target else str(target - number))))
menu()

It seems to me that you are trying to achieve the following:
Get the data from a text file, which you kind of did it
Get a user input to open a new text file: reSit = input("Enter file name for the re-sit: ")
Create a file to write to it fh = open(reSit ,'w')
write to a file fh.write(<a fails student> + '\n')
Close the file
if you want to append to a file replace 3 by fh = open(reSit ,'a')

Related

Writing to a text file, last entry is missing

This code calls no errors, but my text file is not getting betty and her grade. It's only getting the first three out of the four combinations. What am I doing wrong? Thanks!
students = ['fred','wilma','barney','betty']
grades = [100,75,80,90]
for i in range(4):
file = open("grades3.txt", "a")
entry = students[i] + "-" + str(grades[i]) + '\n'
file.write(entry)
file.close
You should use use with open() as ... to automatically open, close and assign the file handle to a variable:
students = ['fred','wilma','barney','betty']
grades = [100,75,80,90]
with open("grades3.txt", "a") as file:
for i in range(4):
entry = students[i] + "-" + str(grades[i]) + '\n'
file.write(entry)
It seems that you are opening the file each iteration of the loop, as well as not calling the file.close function. You should have something like this:
students = ['fred','wilma','barney','betty']
grades = [100,75,80,90]
file = open("grades3.txt", "a")
for i in range(4):
entry = students[i] + "-" + str(grades[i]) + '\n'
file.write(entry)
file.close()
It would be better if you use an approach like this instead of using range():
students = ['fred','wilma','barney','betty']
grades = [100,75,80,90]
with open("grades3.txt","a") as f:
for student, grade in zip(students,grades):
f.write(f"{student}-{grade}\n")

Why does my program ask for input that comes second?

So I've written a simple program that allows user to enter a line they would like to edit and text they would like to put into that line
def edit_line(file):
a_file = open(file, 'r')
list_of_lines = a_file.readlines()
list_of_lines[int(input('What line would you like to edit?: ')) - 1] = input('Write your text here: ') + '\n'
a_file = open(file, 'w')
a_file.writelines(list_of_lines)
a_file.close()
edit_line('sample.txt')
When I run the program it works fine. However, It asks the user to input the text first and the line number second.
What is the reason for this and how can I fix it?
If you want to fix the problem, just split the one line into two:
Instead of:
list_of_lines[int(input('What line would you like to edit?: ')) - 1] = input('Write your text here: ') + '\n'
Do:
index = int(input('What line would you like to edit?: ')) - 1
list_of_lines[index] = input('Write your text here: ') + '\n'
And as the answer #Guy linked explains, when you are doing an assignment line of code, the right hand (value of the variable) is run before the left side.
Validation is everything! What would happen if the user's input for the line number wasn't within the range of lines read from the file?
Here's a more robust approach:
def edit_line(filename):
with open(filename, 'r+') as file:
lines = file.readlines()
while True:
try:
lineno = int(input('What line would you like to edit: '))
if 0 <= lineno < len(lines):
lines[lineno] = input('Write your text here: ') + '\n'
file.seek(0)
file.writelines(lines)
file.truncate()
break
else:
raise ValueError('Line number out of range')
except ValueError as e:
print(e)
edit_line('edit.txt')

How to read a first character from the last line of a file in python

I am writing a scoreboard thingie in python (I am fairly new to the language). Basically user inputs their name and I want the program to read the file to determine, the number that the user is assigned to.
For example, the names in the .txt file are:
Num Name Score
John Doe 3
Mitch 5
Jane 1
How do I now add user no.4 without the user typing the exact string to write, only their name.
Thanks a lot!
I suggest rethinking your design - you probably don't need the line numbers in the file, however you could just read the file and see how many lines there are.
This won't scale if you end up with a lot of data.
>>> with open("data.txt") as f:
... l = list(f)
...
This reads your header
>>> l
['Num Name Score\n', 'John Doe 3\n', 'Mitch 5\n', 'Jane 1\n']
>>> len(l)
4
So len(l)-1 is the last number, and len(l) is what you need.
the easiest way to get the number of lines is by using readlines()
x=open("scoreboard.txt", "r")
line=x.readlines()
lastlinenumber= len(line)-1
x.close()
with open('scoreboard.txt', 'a') as scoreboard: #FIle is opened for appending
username = input("Enter your name!")
scoreboard.write(str(lastlinenumber) + '. ' + str(username) + ": " + '\n')
scoreboard.close()
def add_user():
with open('scoreboard.txt', 'r') as scoreboard:
#Reads the file to get the numbering of the next player.
highest_num = 0
for line in scoreboard:
number = scoreboard.read(1)
num = 0
if number == '':
num == 1
else:
num = int(number)
if num > highest_num:
highest_num = num
highest_num += 1
with open('scoreboard.txt', 'a') as scoreboard: #FIle is opened for appending
username = input("Enter your name!")
scoreboard.write(str(highest_num) + '. ' + str(username) + ": " + '\n')
scoreboard.close()
Thank you guys, I figured it out. This is my final code for adding a new user to the list.

Writing a list into a text file

Using windows 10
Here's a sample of my code, where the problem is:
if choice2 == "d":
amount = int(raw_input("How much money would you like to deposit? Current balance: %i : " % intBalance))
newBalance = intBalance + amount
print "Current balance: %i" %newBalance
f.close()
os.remove("accounts.txt")
f = open("accounts.txt", "a+")
fileVar.remove(accessedAccount[2])
fileVar.remove(accessedAccount[1])
fileVar.remove(accessedAccount[0])
f.write(accessedAccount[0] + "\n")
f.write(accessedAccount[1] + "\n")
newBalance = str(newBalance)
f.write(newBalance + "\n")
for item in fileVar:
f.write("%s\n" %item)
test = raw_input("Waiting for input")
At the bottom is the code that writes the information of the list (called fileVar) into the text file (called f). It does write the information to the list but it messes up the order of the lines which cannot happen with the program I am making because the file must be able to be read back to the program to work later on.
Here is my entire code for context:
import os
import string
again = "y"
f = open('accounts.txt', 'a+')
fileVar = f.read().splitlines()
print fileVar
accessedAccount = []
data = f.read()
choice = raw_input("What would you like to do? (add/remove a bank account, access a bank account): ")
if choice == "a":
while again == "y":
accName = raw_input("Account owner's name: ")
accType = raw_input("Account type: ")
accBal = "0"
f.seek(0, 2)
f.write(accName + "\n")
f.write(accType + "\n")
f.write(accBal)
f.write("\n")
again = raw_input("Add another account?: ")
if choice == "a2":
account = raw_input("What is the name of the account you wish to access?: ")
for i, line in enumerate(fileVar):
if account in line:
for j in fileVar[i:i+3]:
print j
accessedAccount.append(j)
print accessedAccount
balance = accessedAccount[2]
intBalance = int(balance)
print accessedAccount
choice2 = raw_input("This is your bank account. What would you like to do now? (Withdraw/deposit, exit): ")
if choice2 == "d":
amount = int(raw_input("How much money would you like to deposit? Current balance: %i : " %intBalance))
newBalance = intBalance + amount
print "Current balance: %i" %newBalance
f.close()
os.remove("accounts.txt")
f = open ("accounts.txt", "a+")
fileVar.remove(accessedAccount[2])
fileVar.remove(accessedAccount[1])
fileVar.remove(accessedAccount[0])
f.write(accessedAccount[0] + "\n")
f.write(accessedAccount[1] + "\n")
newBalance = str(newBalance)
f.write(newBalance + "\n")
for item in fileVar:
f.write("%s\n" %item)
test = raw_input("Waiting for input")
if choice2 == "w":
amount = int(raw_input("How much money would you like to withdraw? Current balanace: %i : " %intBalance))
newBalance = intBalance - amount
print "Current Balance: %i" %newBalance
f.close()
os.remove("accounts.txt")
f = open ("accounts.txt", "a+")
fileVar.remove(accessedAccount[0])
fileVar.remove(accessedAccount[1])
fileVar.remove(accessedAccount[2])
f.write(accessedAccount[0] + "\n")
f.write(accessedAccount[1] + "\n")
newBalance = str(newBalance)
f.write(newBalance + "\n")
for item in fileVar:
f.write("%s\n" %item)
test = raw_input("Waiting for input")
if choice == "r":
removeChoice = raw_input("What is the name of the account you wish to remove?: ")
f.close()
os.remove("accounts.txt")
f= open("accounts.txt", "a+")
for i, line in enumerate(fileVar):
if removeChoice in line:
for j in fileVar[i:i+3]:
accessedAccount.append(j)
fileVar.remove(accessedAccount[0])
fileVar.remove(accessedAccount[1])
fileVar.remove(accessedAccount[2])
for item in fileVar:
f.write("%s\n" %item)
f.close()
for example, the original text file looks like this:
Ryan
Savings
0
John
Chequings
0
Carly
Savings
0
when it is re-written with edited information, what it is supposed to look like, if 300 dollars were added to Carly's account:
Carly
Savings
300
Ryan
Savings
0
John
Chequings
0
What it looks like instead:
Carly
Savings
300
John
Chequings
Ryan
0
Savings
0
Thank you in advance :)
Not a direct answer to your question, but some pointers which may end up making it much easier for both yourself and others to debug your code.
1) Functions are your friend. See if you can take small tasks and break them up into functions. For example, writing out someone's balance to a file could be a small function, which you might call like:
def write_balance_to_file(account_details):
...function code goes here...
account_details = {name:"Ryan", account:"Savings", balance:1000}
write_balance_to_file(account_details)
Opening and closing the file should be handled within that function, and preferably using:
with open('filename', 'a+') as f:
f.write("A thing to write")
Note that you don't need to close the file manually when doing this.
2) Use a dictionary for storing a person's account details, rather than a list. Multiple accounts can be stored as a list of dictionaries. This makes it a lot easier to read as call such as:
f.write(accessedAccount[0] + "\n")
which becomes:
f.write(accessedAccount['name'] + '\n')
You can then pass in this dictionary to the write_balance_to_file method you will create. :)
3) Consider a tab-separated format for your accounts.txt file. Remember to escape/remove any tabs in your user input. This way each account will be on one line.
4) Possibly a little way in the future for you, but be aware that unit-testing exists, and is good practice. In essence, you can write tests (usually using a test framework such as py.test) which test each function/class/module under different input conditions. Anything that you can't break up into small, testable code fragments (functions or classes) is probably not good code. Writing tests is a great way to identify bugs in your code, and often helps to clarify your thinking. ALWAYS TEST!
For a minimal change that will solve the issue, this is the code that needs to change:
for i, line in enumerate(fileVar):
if account in line:
for j in fileVar[i:i+3]:
print j
accessedAccount.append(j)
This records which entries are part of the accessedAccount however later on you just remove the first occurence of these entries:
fileVar.remove(accessedAccount[2])
fileVar.remove(accessedAccount[1])
fileVar.remove(accessedAccount[0])
but if the entry is something as simple as 0 then it will not necessarily remove it from the correct place, so instead pop the accessed account out of the fileVar when putting them into accessedAccount:
for i, line in enumerate(fileVar):
if account in line:
for j in range(3):
print i+j
accessedAccount.append(fileVar.pop(i+j))
#break # you probably want to stop checking by this point
This will remove the relevent lines from fileVar and put them in accessedAccount so the order of lines will not be messed up by using .remove, and then obviously comment out the calls to .remove:
## fileVar.remove(accessedAccount[2])
## fileVar.remove(accessedAccount[1])
## fileVar.remove(accessedAccount[0])
This should fix the immediate problem of taking out the wrong lines.

Python File errors

File = input("Please enter the name for your txt. file: ")
fileName = (File + ".txt")
WRITE = "w"
APPEND = "a"
file = []
name = " "
while name != "DONE" :
name = input("Please enter the guest name (Enter DONE if there is no more names) : ").upper()
fileName.append(name)
fileName.remove("DONE")
print("The guests list in alphabetical order, and it will save in " + fileName + " :")
file.sort()
for U in file :
print(U)
file = open(fileName, mode = WRITE)
file.write(name)
file.close()
print("file written successfully.")
I am just practicing to write the file in Python, but something bad happened.
Here are still some errors about this:
fileName.remove("DONE")
Still showing 'str' error.
filename=filename+name
Use the above code
Python strings are immutable. Therefore you can't use append() on them. Use += instead:
fileName += name
which is shorthand for
fileName = fileName + name
Note how nothing is appended to the string, instead a new one is created and then assigned to fileName.
Try this.
I thought you have some mistaken in variable name.
aFile = input("Please enter the name for your txt. file: ")
fileName = (aFile + ".txt")
WRITE = "w"
APPEND = "a"
file = []
name = " "
while name != "DONE" :
name = input("Please enter the guest name (Enter DONE if there is no more names) : ").upper()
file.append(name)
file.remove("DONE")
print("The guests list in alphabetical order, and it will save in " + fileName + " :")
file.sort()
for U in file :
print(U)
outputfile = open(fileName, mode = WRITE)
outputfile.write(name)
outputfile.close()
print("file written successfully.")
Just right out the bat, you can not append to a toople.
fileName.append(name) #how can you append or remove anything into or from this when it contains toople?
Another thing, I don't know what version of python you are using but, I never seen expression like this
file = open(fileName, mode = WRITE) #this should be something like (file=open(fileName,"w"))
Just overall check your code. Like I said you can not add or remove stuff from a toople; only in lists and dictionaries.
append is the list's method where as fileName declared in your code is treated as string. If your intention is to append the string to file, open the file in "append" mode and write to it:
with open(aFile + ".txt", "a") as f:
f.write("appended text")

Categories