I'm very new to Python and having a problem with a program I'm doing for a class. main() and create_file work, but when it gets to read_file, the interpreter just sits there. The program is running but nothing is happening.
The answer is probably something very simple, but I just can't see it. Thanks in advance for any help.
I'm using IDLE (Python and IDLE v. 3.5.2)
Here's the code:
import random
FILENAME = "randomNumbers.txt"
def create_file(userNum):
#Create and open the randomNumbers.txt file
randomOutput = open(FILENAME, 'w')
#Generate random numbers and write them to the file
for num in range(userNum):
num = random.randint(1, 500)
randomOutput.write(str(num) + '\n')
#Confirm data written
print("Data written to file.")
#Close the file
randomOutput.close()
def read_file():
#Open the random number file
randomInput = open(FILENAME, 'r')
#Declare variables
entry = randomInput.readline()
count = 0
total = 0
#Check for eof, read in data, and add it
while entry != '':
num = int(entry)
total += num
count += 1
#Print the total and the number of random numbers
print("The total is:", total)
print("The number of random numbers generated and added is:", count)
#Close the file
randomInput.close()
def main():
#Get user data
numGenerate = int(input("Enter the number of random numbers to generate: "))
#Call create_file function
create_file(numGenerate)
#Call read_file function
read_file()
main()
You have an infinite while loop in the function, since entry never changes during the loop.
The Pythonic way to process all the lines in a file is like this:
for entry in randomInput:
num = int(entry)
total += num
count += 1
Related
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'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
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)
def file_contents():
global file_encrypt
encryption_file = input("What is the name of the file?")
file_encrypt = open(encryption_file, 'r')
contents = file_encrypt.read()
print (contents)
ask_sure = input("Is this the file you would like to encrypt?")
if ask_sure == "no":
the_menu()
This part of the code opens the file the user enters, right? There are no real problems here.
def key_offset():
key_word = ''
count = 0
total = 0
while count < 8:
num = random.randint (33, 126)
letter = chr(num)
key_word = key_word + letter
count = count + 1
offset = ord(letter)
total = total + offset
print("Make sure you copy the key for decryption.")
if count == 8:
total = total/8
total = math.floor(total)
total = total - 32
print(key_word)
return total
This is the part where it calculates the offset and etc etc. Once again no problems here.
def encrypting():
file = file_contents()
total = key_offset()
encrypted = ''
character_number = 0
length = len(file_encrypt)
And then this is where the problem appears, I have made the variable file_encrypt global in the first block of code, so therefore it should work. I have tried calling it under another variable like file_en = file_encrypt and used file_en in the length calculating, but it keeps saying it has no length... I have tried asking friends and my teacher, but they seem clueless. The problem is that every time i get to this part it says that file_encrypt has no length or the other way I tried it, file_en has no length, something to do with TextWrapper.io.
file_encrypt is a file pointer, which does indeed not have a length. The contents of your file are in contents, but that is a variable local to the file_contents function.
Really you should not be using global variables; there isn't any reason to here. Instead, return the actual data - contents - from file_contents, then you can use it in the calling function.
There are a few issues with your code, but ignoring those for now, I think your main problems are:
1) The function "file_contents" doesn't return anything, I suspect you want to return "contents". Hard to say without knowing what you want to do with the "file" variable.
def encrypting():
file = file_contents() # <--
2) As others have said, "file_encrypt" is a pointer to a file, although in this function you didn't declare it as global, so it's probably None.
def encrypting():
file = file_contents()
total = key_offset()
encrypted = ''
character_number = 0
length = len(file_encrypt) # <--
So, these modifications should give you what you need:
def file_contents():
global file_encrypt
encryption_file = input("What is the name of the file?")
file_encrypt = open(encryption_file, 'r')
contents = file_encrypt.read()
print (contents)
ask_sure = input("Is this the file you would like to encrypt?")
if ask_sure == "no":
the_menu()
return contents # <-- ADDED
def encrypting():
contents = file_contents() # <-- MODIFIED
total = key_offset()
encrypted = ''
character_number = 0
length = len(contents) # <-- MODIFIED
I am writing a program that will open a specified file then "wrap" all lines that are longer than a given line length and print the result on the screen.
def main():
filename = input("Please enter the name of the file to be used: ")
openFile = open(filename, 'r+')
file = openFile.read()
lLength = int(input("enter a number between 10 & 20: "))
while (lLength < 10) or (lLength > 20) :
print("Invalid input, please try again...")
lLength = int(input("enter a number between 10 & 20: "))
wr = textwrap.TextWrapper()
wr.width = lLength
wr.expand_tabs = True
wraped = wr.wrap(file)
print("Here is your output formated to a max of", lLength, "characters per line: ")
print(wraped)
main()
When I do this instead of wrapping it prints everything in the file as a list with commas and brackets, instead of wrapping them.
textwrap.TextWrapper.wrap "returns a list of output lines, without final newlines."
You could either join them together with a linebreak
print('\n'.join(wrapped))
or iterate through and print them one at a time
for line in wrapped:
print(line)