I'm trying to make a new file at the end of a program to append info into, however the file isn't being created for some reason (the place in my code to look at is the #curve area). My best guess is that the variable "filename" established at the beginning of the program, isn't carrying all the way down to where I establish the new file name. My code is as follows:
import statistics
# input
filename = input("Enter a class to grade: ")
try:
# open file name
open(filename+".txt", "r")
print("Succesfully opened", filename,".txt", sep='')
print("**** ANALYZING ****")
with open(filename+".txt", 'r') as f:
counter1 = 0
counter2 = 0
right = 0
answerkey = "B,A,D,D,C,B,D,A,C,C,D,B,A,B,A,C,B,D,A,C,A,A,B,D,D"
a = []
# validating files
for line in f:
if len(line.split(',')) !=26:
print("Invalid line of data: does not contain exactly 26 values:")
print(line)
counter2 += 1
counter1 -= 1
if line.split(",")[0][1:9].isdigit() != True:
print("Invalid line of data: wrong N#:")
print(line)
counter2 += 1
counter1 -= 1
if len(line.split(",")[0]) != 9:
print("Invalid line of data: wrong N#:")
print(line)
counter2 += 1
counter1 -= 1
counter1 += 1
#grading students
score = len(([x for x in zip(answerkey.split(","), line.split(",")[1:]) if x[0] != x[1]]))
score1 = 26 - score
score2 = score1 / 26
score3 = score2 * 100
a.append(score3)
sscore3 = str(score3)
# results file
results = open(filename+"_grades.txt", "a")
results.write(line.split(",")[0])
results.write(",")
results.write(sscore3[:2])
results.write("\n")
results.close()
# in case of no errors
if counter2 == 0:
print("No errors found!")
# calculating
number = len(a)
sum1 = sum(a)
max1 = max(a)
min1 = min(a)
range1 = max1 - min1
av = sum1/number
# turn to int
av1 = int(av)
max2 = int(max1)
min2 = int(min1)
range2 = int(range1)
# median
sort1 = sorted(a)
number2 = number / 2
number2i = int(number2)
median = a[number2i]
median1 = int(median)
# mode
from statistics import mode
mode = mode(sort1)
imode = int(mode)
# printing
print ("**** REPORT ****")
print ("Total valid lines of data:", counter1)
print ("Total invalid lines of data:", counter2)
print ("Mean (average) score:", av1)
print ("Highest score:", max2)
print("Lowest score:", min2)
print("Range of scores:", range2)
print("Median Score:", median1)
print("Mode score(s):", imode)
# curve
part = input("Would you like to apply a curve to the scores? (y)es or (n)o?")
if part == "y":
newmean = input("Enter desired mean score:")
part1 = newmean - av1
part2 = sscore3 + part1
results = open(filename+"_grades_with_curve.txt", "a")
results.write(line.split(",")[0])
results.write(",")
results.write(sscore3[:2])
results.write(",")
results.write(part2)
results.write("\n")
results.close()
except:
print("File cannot be found.")
and It skips to the except block when I enter "y" at the end to try and create the new list, meaning the issue is within creating this new list.
The code is too long and requires reorganization.
It is likely, there are other problems with your code and you are trying to fix wrong one.
Few hints:
Do not open file without assigning the file object to a variable
open(filename+".txt", "r")
You open the file and have no chance to close it as you ignore the returned
file object.
Use with block to open/close your files
with open(input_fname, 'r'):
# work with the file
Learn doing so everywhere.
Do not reopen file for writing results
Your code repeatedly opens the result file (in "a" mode). You have better opening it only once.
You may even open multiple files within one context block:
with open(input_fname, 'r') as f, open(output_fname, "a") as results:
# work with the files
Reuse once calculated result
In many places you split the line: line.split(",").
You shall put the result into variable and reuse it.
rec = line.split(",")
Never ignore exceptions!!! (most serious problem)
The final block is catching all exceptions without giving you any sign, what went wrong (or even
worse, it tells you probably wrong information that the file was not found).
So instead of:
try:
# some code
except:
print("File not found.")
at least reraise the exception to learn from it:
try:
# some code
except:
print("File not found.") # this is probably to be removed as misleading message
raise
In fact, you can completely ignore complete top level try - except block and let the exception show
up telling you what went wrong.
Split your code into smaller chunks.
Having the code split to smaller functions shall simplify debugging and usage
Related
I have a program that reads numbers from a .txt file, the numbers are separated by a coma, and the program assigns them to variables to work out quadratic equations. I need to know what different ways I can check the file for txt, and display an error message.
I currently have the program working fine, it does check for text and gives an error message (The text file is empty)if the file is blank. However somewhere in my code I have stuffed up, because if there is text in the file and the program does its equations, it also gives the error message. I know somewhere I have muddled up my loops.
Here is the code, without the functions:
# Main Program
userInput = True
while userInput == True :
file = input("\nPlease input text file name: ")
file = file + ".txt"
if os.path.exists(file):
with open(file, "rt") as text_file:
for line in text_file:
a,b,c = [float(i.strip()) for i in line.split(',')]
if a == 0:
count = count + 1
print("\nEquation No.", count)
print("a =", a," b =", b," c =", c)
print("Cannot be a quadratic equation if 'a' is zero")
else:
count = count + 1
print("\nEquation No. ", count)
print("a =", a," b =", b," c =", c)
equationroots(a, b, c)
else:
userInput = False
if userInput == False:
print("\nThe text file is empty")
break
else:
print("\nThe file cannot be found")
continue
input("\nEnd")
And here is the output, with just two lines in a .txt file:
Welcome
Please input text file name: test1
Equation No. 1
a = 0.0 b = 2.0 c = 4.0
Cannot be a quadratic equation if 'a' is zero
Equation No. 2
a = 3.0 b = 7.0 c = 12.0
There are two distinct complex Roots
-1.1667 + i 9.7468
-1.1667 - i 9.7468
The text file is empty
End
As you can see in the output, I am still getting the error message. I would appreciate any input in solving my problem. Thanks
That else statement doesn't do what you want it to after the for line in text_file: bit. Here's your code currently:
with open(file, "rt") as text_file:
for line in text_file:
#some code that analyses the file and prints some output data
# this else statement is getting triggered regardless of if the 'for' loop runs or not
else:
userInput = False
if userInput == False:
print("\nThe text file is empty")
break
one way to fix this is to create a boolean that gets set to some value if you enter the for loop:
# Main Program
while userInput == True:
# reset this to True every new loop of the parent while loop
empty = True
# ...
if os.path.exists(file):
with open(file, "rt") as text_file:
for line in text_file:
# the for loop was entered, don't print the empty file error message
empty = False
# ...
# only run this if the 'for' loop hasn't been run this iteration of the parent 'while' loop
if empty:
userInput = False
if userInput == False:
print("\nThe text file is empty")
break
# ...
(# ... signifies code that was cut out because it's not relevant to the point I'm making)
Any time there's a section of code that you'll be repeating a lot, it's good to use a function.
Here I'm checking if the file is literally empty, a single white-space wouldn't count as empty.
You never change your a,b,c to integers, so a == 0 will never be true.
def output_equation(count, a, b, c):
print("\nEquation No.", count)
print("a =", a," b =", b," c =", c)
if a == 0:
print("Cannot be a quadratic equation if 'a' is zero")
else:
equationroots(a, b, c)
return count + 1
count = 0
while True:
file = input("\nPlease input text file name, or press Enter to exit: ")
if not file:
break
file = file + ".txt"
if not os.path.exists(file):
print("\nThe file cannot be found.")
continue
if not os.path.getsize(file):
print("\nThe file is empty.")
continue
with open(file) as f:
for line in f:
a,b,c = map(int, line.split(','))
count = output_equation(count, a, b, c)
print("\nEnd")
I think the best way to check if the file is empty, is with a guard clause. We can read the contents of the file right after opening it. This way if we read the value (and strip the whitespace) and the content is blank, we can immediately break from the while loop and inform the user that the file is empty.
To check if the file exists or not, I think using a guard clause here as well, will definitely help with your readability. Let me know if that helped.
import os
# Main Program
userInput = True
while userInput == True :
file = input("\nPlease input text file name: ")
file += ".txt"
if not os.path.exists(file):
print("\nThe file cannot be found")
continue
with open(file, "rt") as text_file:
if text_file.read().strip() == "":
print("\nThe text file is empty")
break
# Move text cursor to the beginning of file
text_file.seek(0)
for line in text_file:
a, b, c = [float(i.strip()) for i in line.split(',')]
if a == 0:
count += 1
print("\nEquation No.", count)
print("a =", a," b =", b," c =", c)
print("Cannot be a quadratic equation if 'a' is zero")
else:
count += 1
print("\nEquation No. ", count)
print("a =", a," b =", b," c =", c)
equationroots(a, b, c)
input("\nEnd")
So, I'm doing this assignment and I can't seem to figure out how to continue on to the next step.
assignment output example
The file numbers.txt contains the following numbers all on separate lines (25, 15, 5, six, 35, one, 40).
My problem is that I can only print out one ValueError message (six), but I need to be able to print out both messages (invalid literal for int() with base 10: 'six\n', invalid literal for int() with base 10: 'one\n').
Since I can't get the codes to move on to the next iteration, my average only adds 25, 15, and 5.
I've only been learning Python for a month so I don't know if there's a simple way to solve all these problems.
Below is the code I am working on.
def main():
while True:
try:
filename = input("Enter a file name: ")
infile = open(filename, "r")
except IOError:
print("[Error No. 2] No such file or directory:", filename)
continue # continue to next iteration
else:
break
data = infile.readline().strip()
numbers = data.split()
total = 0
count = 0
try:
infile = open(filename, "r") #somehow without this, the first line won't print
for line in infile:
num = int(line)
print(num)
total += num
count += 1
print("The average is: ", total/count)
except ValueError as err:
print(err)
finally:
print(total/count)
main()
You can repositioning your try statement in the second loop like so:
data = infile.readline().strip()
numbers = data.split()
total = 0
count = 0
infile = open(filename, "r")
for line in infile:
try:
num = int(line)
print(num)
total += num
count += 1
except ValueError as err:
print(err)
print("The average is: ", total/count)
This way, you won't exit the loop once you encounter an error message, and will simply print it and move on to the next line.
Try the below
# open the file using 'with' - it will make sure that the file will be closed
with open('input.txt') as f:
values = []
# read the lines into a list
lines = [l.strip() for l in f.readlines()]
for line in lines:
# try to convert to int
try:
x = int(line)
values.append(x)
except ValueError as e:
print(e)
# calculate the average
print(f'Avg: {sum(values)/len(values)}')
input.txt
25
15
5
six
35
one
40
output
invalid literal for int() with base 10: 'six'
invalid literal for int() with base 10: 'one'
Avg: 24.0
You need to indent your while True as currently the main function is causing an error.
You should also do an if line == ‘six’:
line = 6
You can set the try-except block inside the for loop which should produce the correct results.
data = infile.readline().strip()
numbers = data.split()
total = 0
count = 0
infile = open(filename, "r")
for line in infile:
try:
num = int(line)
total += num
count += 1
except ValueError as err:
print(err)
print("The average is: ", total/count)
I would like to be able to take the test scores the user inputs and write to an external text file. Then have the application read off the values from the and calculate the average. However, I am unsure as to how to implement the python syntax within the loop and the functions. I've attempted to utilize my resources to get a better idea of how to do this, but I've been having some trouble understanding how python handles external files. In addition, would using append be better than write in this scenario?
Current Syntax:
def testAvgCalculation():
#Variables
total = 0
total_quiz = 0
while True:
#User Input and Variable to stop loop
inpt = input("Enter score: ")
if inpt.lower()== 'stop':
break
#Data Validation
try:
if int(inpt) in range(1,101):
total += int(inpt)
total_quiz += 1
else:
print("Score too small or Big")
except ValueError:
print("Not a Number")
return total, total_quiz
def displayAverage(total, total_quiz):
average = total / total_quiz
print('The Average score is: ', format(average, '.2f'))
print('You have entered', total_quiz, 'scores')
#Main Function
def main():
total, total_quiz = testAvgCalculation()
displayAverage(total, total_quiz)
#Run Main Function
main()
This is hacky as heck, but I tried to work with what was already there. I split the data validation section of the original function off into a separate function. In main() it returns its value counter, which keeps track of how many values were entered, to calculate_average(), which then reads the file line by line until counter becomes 0, which means it's about to read the word "stop" (which allows EOF recognition via the 'and' in the if statement), performs the calculation and returns its values.
def write_file():
#Variables
counter = 0
file = open("Scores.txt", "w")
while True:
#User Input and Variable to stop loop
inpt = input("Enter score: ")
file.write(inpt + "\n")
if inpt.lower()== 'stop':
file.close()
break
counter += 1
return counter
def calculate_average(counter):
total = 0
total_quiz = counter
scores = open("Scores.txt", "r")
s = ""
try:
while counter > 0 and s != 'stop':
s = int(scores.readline())
if int(s) in range(1,101):
total += int(s)
counter -= 1
else:
print("Invalid data in file.")
except ValueError:
print("Invalid data found")
return total, total_quiz
def displayAverage(total, total_quiz):
average = total / total_quiz
print('The Average score is: ', format(average, '.2f'))
print('You have entered', total_quiz, 'scores')
#Main Function
def main():
total, total_quiz = calculate_average(write_file())
displayAverage(total, total_quiz)
#Run Main Function
main()
NOTE: the file is created initially in write mode which overwrites the file each time so you never need a new one. if you want to keep a record you might like to change it to append, though you'll need to manage extracting the proper lines from among old input.
Not pretty at all, but should give you an idea of how to accomplish what you were going for.
I have been working on this code for a couple of hours now, and I am rather unsure what the problem is.
import random#imports random
import os#Imports os
print("Welcome to the maths quiz") # Welcomes user to quiz
score = (0)
def details():
plr_name = input ("Please Input Name:") # Asks user for name
plr_class = input("Input class number: ") # Asks the user for class numer
return (plr_name, plr_class)
def Q():
while qno < 10: # loops while qno is under 10
ran_num1 = random.randint(1,99) # Generates the first random number
ran_num2 = random.randint(1,99) # Generates the second random number
ran_fun = random.choice("X-+") # Picks a random function
print(ran_num1,ran_fun,ran_num2,"=") # Prints the Sum for the user
if ran_fun == "X":
sum_ans = ran_num1 * ran_num2 # Does the sum if it is a multiplication
if ran_fun == "+":
sum_ans = ran_num1 + ran_num2 # Does the sum if it is a addition
if ran_fun == "-":
sum_ans = ran_num1 - ran_num2 # Does the sum if it is a subtraction
plr_ans = int(input()) # Gets the user's answer
if plr_ans == sum_ans:
print("Correct!") # Prints correct
score = score + 1 # Adds 1 to score
else:
print("Incorrect!")
qno = qno + 1 # Adds 1 to qno
def plr_list_make(lines, listoreder):
index = 0
plr_names =[]
plr_scores =[]
for line in lines:
if listorder == 1:
column =0
rev = False
else:
column = 1
rev = True
return sorted(zip(plr_names, plr_scores),key = lambda x:(x[column]),reverse = rev)
def fileUP(plr_name, score, line ):
found = False
index = 0
for line in lines:
if line.startswith(plr_name):
line = line.strip("\n") + ","+str(score+"\n")
lines[index] = line
found = True
index = index + 1
if not found:
lines.append(plr_name+"|" +str(score)+"\n")
return lines
def save (plr_name, plr_class, score):
filename = "QuizScore_"+plr_class+".txt"
try:
fileI = open(filename)
except IOError:
fileI = open(filename, "w+")
fileI = open(filename)
lines = fileI.readlines()
fileI.close
lines = FileUP(plr_name, score, lines)
fileO = open(filename, "w")
fileO.writelines(lines)
fileO.close
def disp_list(): ## intialise_list
student_list=[]
filename = "QuizScore_"+plr_class+".txt"
try:
## open file read into list "lines"
input_file = open(filename)
lines = input_file.readlines() ## read file into list "lines"
input_file.close
student_list = create_student_list(lines, listorder) ### update "lines" with student list as requested by user
## output sorted list
for counter in range(len(student_list)):
print ("Name and Score: ", student_list[counter][0], student_list[counter][1])
except IOError:
print ("no class file!!!")
def menu():
print ("1 Test")
print ("2 Alphabetical")
print ("3 Highscore")
print ("4 Avg Score")
def Run():
selection = 0
while selection != 5:
menu()
option = int(input("Please select option: "))
if option == 1:
name, plr_class = details()
save(name, plr_class, Q())
else:
plr_class = input("input class ")
disp_list(plr_class, option-1)
Run()
Errors:
Traceback (most recent call last):
File "C:\Users\user\Documents\CharlieStockham\cgsca\ca2.py", line 117, in
Run()
File "C:\Users\user\Documents\CharlieStockham\cgsca\ca2.py", line 113, in Run
save(name, plr_class, Q())
File "C:\Users\user\Documents\CharlieStockham\cgsca\ca2.py", line 74, in save
lines = FileUP(plr_name, score, lines)
NameError: global name 'FileUP' is not defined
Line 110:
name, plr_class = details()
But the details function does not return anything - so Python tries to assign the default return value None to the tuple name, plr_class. It can't do this, because None is not an iterable (you can't assign two things to it). To fix it, add the following line to your details function:
return (plr_name, plr_class)
(I haven't tested this.)
I like your game but it's buggy as a mofo :P
score and qno aren't properly defined. Define them in the functions that need them, define them globally or pass them to the relevant functions as arguments.
details() doesn't return anything but you still attempt to use its output to define two other variables. Add return (plr_name, plr_class) to details()
Every time you cast user input to int without checking its value, your program will crash if an int can't be cast. This applies here:
option = int(input("Please select option: "))
here
plr_ans = int(input())#Gets the user's answer
and elsewhere.
Since your program is input-heavy you could make a a function to which you pass the expected datatype and an optional string to display to the user. This way you wouldn't have to write try/except 10 times and your program wouldn't crash on unexpected input.
In def fileUP(plr_name, score, line ): you have for line in lines: but lines isn't defined. Thus, the save() function that calls FileUP() also fails. Also, FileUP and fileUP are not the same thing. You call the function with a capital "f" but the defintion of the function calls it fileUP with a lower case "f".
While we're at it, the file handling in def save (plr_name, plr_class, score):looks weird. The standard way of opening files for simple reading and writing in Python is via with open().
disp_list() should take one or two arguments but it doesn't at the moment so this error is raised:
TypeError: disp_list() takes 0 positional arguments but 2 were given
These 2 positional arguments were given here:
disp_list(plr_class, option-1)
So I have a question that requires this The features : color,size,flesh and class are separated by spaces. Write a Python program that asks the user for the names of the input file (in this case animals.txt) and the output file (any name). The program reads in the lines of the input file, ignores comment lines (lines starting with #) and blank lines and computes and prints the answers to the following questions:
Total number of animals?
Total number of dangerous animals?
Number of large animals that are safe?
Number of animals that are brown and dangerous?
Number of safe animals with red color or hard flesh?
So I finished the program and everything seems to be working but so far when I enter the code and initiate the program, everything works, no errors, nothing but no output file gets generated. I don't know what is wrong exactly but if someone could point me in the right direction it would be highly appreciated.
import os.path
endofprogram = False
try:
filename1 = input("Enter the name of input file: ")
filename2 = input("Enter the name of output file: ")
while os.path.isfile(filename2):
filename2 = input("File Exists! Enter new name for output file: ")
infile = open(filename1, 'r')
ofile = open(filename2, "w")
except IOError:
print("Error reading file! Program ends here")
endofprogram = True
if (endofprogram == False):
alist = []
blist = []
clist = []
largesafe = 0
dangerous = 0
browndangerous = 0
redhard = 0
for line in infile:
line = line.strip("\n")
if (line != " ") and (line[0] != "#"):
colour, size, flesh, clas = line.split('\t')
alist = alist.append(colour)
animals = alist.count()
while clas == "dangerous":
dangerous = dangerous + 1
while size == "large" and clas == "safe":
largesafe = largesafe + 1
while colour == "brown" and clas == "dangerous":
browndangerous = browndangerous + 1
while colour == "red" and flesh == "hard":
redhard = redhard + 1
ofile.write(print("Animals = \n", animals))
ofile.write(print("Dangerous = \n", dangerous))
ofile.write(print("Brown and dangerous = \n", browndangerous))
ofile.write(print("Large and safe = \n", largesafe))
ofile.write(print("Safe and red color or hard flesh= \n", redhard))
infile.close()
ofile.close()
Your indentation has completely messed the program up. The biggest offender is this section:
except IOError:
print("Error reading file! Program ends here")
endofprogram = True
if (endofprogram == False):
The if line will only ever be executed right after the endofprogram = True line, at which point endofprogram == False will be false, and so nothing in the if block — which include the rest of the program — will be executed. You need to dedent everything from the if onwards by one level.
Maybe you can remove the print inside ofile.write
ofile.write(print("Animals = \n", animals))
to
ofile.write("Animals = \n" + str(animals))