在 Python3 中编辑 csv 文件
Editing a csv file in Python3
您好,我对使用 python 编辑 csv 文件有点陌生。我正在做一个项目。这是一个简单的成绩计算器,可读取名为 new_grade.csv 的 csv 文件。我的脚本计算每个学生的平均成绩。我不小心对我的脚本进行了硬编码,并且在读取多个 csv 行时遇到了问题。
我的问题是如何将我的代码修改为 运行 任意一行数据。我的代码只处理第一行数据。任何帮助将不胜感激。
我的 csv 文件:
Smithy, James, 100, 78, 92, 92, 85, 85, 95, 100, 75, 85, 50, 85, 87, 95, 95, 80, 80, 96, 95, 95, 95, 85, 79, 95, 85, 95, A, A+, A, B, A+, F, C, B, A, A, A, A, 85, 95, 82, 91
Gadget, John, 0, 0, 92, 92, 85, 60, 85, 100, 75, 85, 50, 85, 0, 95, 85, 70, 70, 0, 95, 95, 95, 85, 0, 95, 0, 95, F, F, F, B, A+, A, C, B, C, F, F, F, 45, 75, 82, 31
Phillips, David, 100, 78, 92, 92, 85, 90, 85, 100, 75, 85, 50, 85, 87, 95, 85, 80, 80, 96, 95, 95, 95, 85, 79, 95, 85, 95, A, A+, A, B, A+, A, A, B, C, A, A, A, 85, 95, 82, 91
我的一行数据能解决的代码:
def main():
try:
import csv
import sys
# This section opens up the file grades.csv. It will then read the data and then takes that data and converts
# that data into a list. When it's in a list we can splice the data to compute averages.
with open("new_grade.csv", 'r') as f:
list(csv.reader(f)) # had data = variable
while True:
# function to remove \n character from csv file
def remove_newlines(fname):
flist = open(fname).readlines()
return [s.rstrip('\n') for s in flist]
old_line = (remove_newlines("new_grade.csv"))
# For required output:
line = old_line[0].split(', ') # This open up the line of the file. For instance this opens up line 1 of
# file.
if len(line) > 44: # This checks to make sure that the data doesn't exceed 44 indexes
print('The data in your file exceeds the maximum amount. Check line 1 of your file. ')
sys.exit(1)
def student():
print((line[0]) + ',' + ' ' + (line[1]), end=', ') # This finds the student's name
def preparation_assignment_average(): # This will compute the preparation assignment average.
global prep
prep = 0
for i in (line[2:16]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
prep = prep + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
sys.exit(1) # This ends the program if it fails the if statement
print(round((prep / 14), 2), end=', ')
def lab_score_average(): # This will compute the lab score average
global lab
lab = 0
for i in (line[17:28]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
lab = lab + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
sys.exit(1) # This ends the program if it fails the if statement
print(round((lab / 12), 2), end=', ')
def post_lab_average(): # This calculates the post lab average of the student. It takes a letter and
# converts the letter to a score that is an integer.
global score
score = 0
for i in (line[28:39]):
if i == "A+":
score += 100
elif i == "A":
score += 95
elif i == "A-":
score += 90
elif i == "B":
score += 85
elif i == "C":
score += 75
elif i == "D":
score += 60
elif i == "F":
score += 0
elif i is not "A+" or "A" or "A-" or "B" or "C" or "D" or "F":
print('Your file is not formatted to the standard of the program. On line 1 of your file, '
'you have\na score where a letter grade should be. Please check file and rerun the '
'program.')
sys.exit(1)
print(round((score / 12), 2), end=', ')
def exam_average(): # This will compute the exam average for the student
global exam
exam = 0
for i in (line[40:44]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
exam = exam + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
sys.exit(1) # This ends the program if it fails the if statement
print(round((exam / 4), 2), end=', ')
def overall_weighted_class_average(): # This will compute the overall class average for the student
global weighted_class_grade
global weighted_prep
global weighted_lab
global weighted_score
global weighted_exam
weighted_prep = ((prep / 14) * .10) # This is calculating the weighted average for a
weighted_lab = ((lab / 12) * .20) # This is calculating the weighted average for b
weighted_score = ((score / 12) * .10) # This is calculating the weighted average for score
weighted_exam = ((exam / 4) * .60) # This is calculating the weighted average for exam
weighted_class_grade = round((weighted_prep + weighted_lab + weighted_score + weighted_exam), 2)
print(weighted_class_grade, end=', ')
def letter_grade_for_class(): # This will take the weighted class grade and it will print that grade
# according to the range
letter = weighted_class_grade
while True:
if 95 < letter <= 100:
print("A+")
break
elif letter == 95:
print("A")
break
elif 90 <= letter <= 94:
print("A-")
break
elif 85 < letter <= 89:
print("B+")
break
elif letter == 85:
print("B")
break
elif 80 <= letter <= 84:
print("B-")
break
elif 75 < letter <= 79:
print("C+")
break
elif letter == 75:
print("C")
break
elif 70 <= letter <= 74:
print("C-")
break
elif 65 < letter <= 69:
print("D+")
break
elif letter == 65:
print("D")
break
elif 60 <= letter <= 64:
print("D-")
break
elif letter <= 59:
print("F")
break
def call_functions(): # This takes all the definitions and makes it into one definition
student()
preparation_assignment_average()
lab_score_average()
post_lab_average()
exam_average()
overall_weighted_class_average()
letter_grade_for_class()
return ''
break
# After computing all the averages for the line of data it then writes it to a new file
original_stdout = sys.stdout
file = open('test_file.csv', 'x') # The x will not save the file if it already exists
sys.stdout = file
for i in call_functions():
file.writelines('\n%s' % i)
sys.stdout = original_stdout
file.close()
f.close()
except ValueError: # displays when one of the letters is out of its index
print('Sorry, one of the letters in the file is out of place. Please check the file again to make sure that \n'
'the letter is not where the numbers are supposed to be. Check indexes 29-39. That is where the \n'
'letter grades for the file should be.')
sys.exit(1)
except FileNotFoundError: # displays error if there is no file by that name
print("Sorry, the current file that you have selected is not a File.")
sys.exit(1)
except IndexError: # this displays when there is no data in the file
print('The file that you have selected does not contain any grades. Please check the file again.')
sys.exit(1)
except PermissionError:
print('The file that you are trying to save is already a file. The file is protected and can not be written.')
sys.exit(1)
except FileExistsError:
print('The file that you are trying to save is already a file. Please rename your file or delete that file '
'and rerun the program.')
sys.exit(1)
if __name__ == "__main__":
main()
我认为有两件事可以解释您所看到的行为并提示您可以修改代码的方式。
行line = old_line[0].split(', ')
表示您只阅读文件的第一行。你应该有某种循环访问文件的每一行作为 line = old_line[index].split(',')
.
下面的循环可能并没有按照您的想法进行:
for i in call_functions():
file.writelines('\n%s' % i)
sys.stdout = original_stdout
file.close()
call_functions()
方法实际上 returns 一个空字符串,所以这个循环的主体实际上根本没有 运行。 call_functions()
只调用一次,这就是您在输出 csv 中只看到一行输出的原因。您需要为 CSV 中的每一行调用 call_functions()
。
这篇文章很长 post 所以我将把它分成几部分,以提高可读性。完整代码在更改说明之后。
第一部分
我复制并粘贴了您的代码,PyCharm 和 Visual Studio 在第 72 行为您的 post_lab_average()
函数捕获了 SyntaxWarning 错误。
这是触发它的 elif
语句:
elif i is not "A+" or "A" or "A-" or "B" or "C" or "D" or "F":
该程序只是希望您将 is not
更改为 !=
,但老实说,您在这里不需要表达式,因为您已经要检查所有其他字母了。你真的只需要 else:
而不是 elif i != 'A+' or 'A' or ...
在进行了我将要解释的所有其他更改后,程序 运行 在本节中再次出现问题,其中 if i == "A+":
如果有额外的 space 将无法工作它正在检查的行,即 i = " A+"
。为了解决这个问题,我们将表达式改写为 if "A+" in i:
,这样我们就可以检查 "A+"
,而不管是否有额外的 space。
您的 post_lab_average()
应该如下所示:
def post_lab_average():
global score
score = 0
for i in (line[28:39]):
if "A+" in i:
score += 100
elif "A" in i:
score += 95
elif "A-" in i:
score += 90
elif "B" in i:
score += 85
elif "C" in i:
score += 75
elif "D" in i:
score += 60
elif "F" in i:
score += 0
else:
print('Your file is not formatted to the standard of the program. On line 1 of your file, '
'you have\na score where a letter grade should be. Please check file and rerun the '
'program.')
exit(1)
此外,在您调用 sys.exit(1)
终止程序的整个代码中,sys.
是不必要的,仅使用 exit(1)
即可。
第二部分
接下来弹出的错误是异常,FileExistsError
为行
file = open('test_file.csv', 'x')
最后,我们会将数据附加到 csv 文件中,因此我们将在 main()
函数的开头包含这行代码:
import os
try:
os.remove('test_file.csv')
except FileNotFoundError:
pass
这将始终删除文件(如果存在),您可以在最后删除 except FileExistsError:
,因为异常将不再触发。
第三部分
当使用 with open()
打开文件时,默认设置是读取文件,因此您不需要添加 'r'
您实际上不需要 remove_newlines()
函数,我们'将打开文件并将数据分配给列表,如下所示:
with open('new_grade.csv') as file:
student_list = list(csv.reader(file))
第四部分
现在我们将使用计数器将您的 while True
循环调整为 运行,当所有列表达到 运行 时停止。
count = 0
while count < len(student_list):
line = student_list[count]
count += 1
循环将继续,直到 运行 遍历了 student_list
中的所有子列表。您必须在循环结束时摆脱您的 break
才能正常工作。
第五部分
快完成了! 运行 当前状态下的文件将生成一个仅包含条目中最后一名学生的文件。为了解决这个问题,我们将缩进写入文件的代码块,以便它 运行 在每个循环结束时而不是在循环结束后。我还重新格式化为使用 with open('a')
这样我们就可以附加我们的数据而不是覆盖。
original_stdout = sys.stdout
with open('test_file.csv', 'a') as file:
sys.stdout = file
for i in call_functions():
file.writelines('\n%s' % i)
sys.stdout = original_stdout
最终代码
def main():
try:
import csv
import sys
import os
# Checks if file exists and removes it if found
try:
os.remove('test_file.csv')
except FileNotFoundError:
pass
# Opens the data file and assigns it to a list
with open('new_grade.csv') as file:
student_list = list(csv.reader(file))
# Loops through each student in list
count = 0
while count < len(student_list):
line = student_list[count]
count += 1
if len(line) > 44: # This checks to make sure that the data doesn't exceed 44 indexes
print('The data in your file exceeds the maximum amount. Check line 1 of your file. ')
sys.exit(1)
def student():
print((line[0]) + ',' + ' ' + (line[1]), end=', ') # This finds the student's name
def preparation_assignment_average(): # This will compute the preparation assignment average.
global prep
prep = 0
for i in (line[2:16]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
prep = prep + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
exit(1) # This ends the program if it fails the if statement
print(round((prep / 14), 2), end=', ')
def lab_score_average(): # This will compute the lab score average
global lab
lab = 0
for i in (line[17:28]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
lab = lab + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
exit(1) # This ends the program if it fails the if statement
print(round((lab / 12), 2), end=', ')
def post_lab_average(): # This calculates the post lab average of the student. It takes a letter and
# converts the letter to a score that is an integer.
global score
score = 0
for i in (line[28:39]):
if "A+" in i:
score += 100
elif "A" in i:
score += 95
elif "A-" in i:
score += 90
elif "B" in i:
score += 85
elif "C" in i:
score += 75
elif "D" in i:
score += 60
elif "F" in i:
score += 0
else:
print('Your file is not formatted to the standard of the program. On line 1 of your file, '
'you have\na score where a letter grade should be. Please check file and rerun the '
'program.')
exit(1)
print(round((score / 12), 2), end=', ')
def exam_average(): # This will compute the exam average for the student
global exam
exam = 0
for i in (line[40:44]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
exam = exam + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
exit(1) # This ends the program if it fails the if statement
print(round((exam / 4), 2), end=', ')
def overall_weighted_class_average(): # This will compute the overall class average for the student
global weighted_class_grade
global weighted_prep
global weighted_lab
global weighted_score
global weighted_exam
weighted_prep = ((prep / 14) * .10) # This is calculating the weighted average for a
weighted_lab = ((lab / 12) * .20) # This is calculating the weighted average for b
weighted_score = ((score / 12) * .10) # This is calculating the weighted average for score
weighted_exam = ((exam / 4) * .60) # This is calculating the weighted average for exam
weighted_class_grade = round((weighted_prep + weighted_lab + weighted_score + weighted_exam), 2)
print(weighted_class_grade, end=', ')
def letter_grade_for_class(): # This will take the weighted class grade and it will print that grade
# according to the range
letter = weighted_class_grade
while True:
if 95 < letter <= 100:
print("A+")
break
elif letter == 95:
print("A")
break
elif 90 <= letter <= 94:
print("A-")
break
elif 85 < letter <= 89:
print("B+")
break
elif letter == 85:
print("B")
break
elif 80 <= letter <= 84:
print("B-")
break
elif 75 < letter <= 79:
print("C+")
break
elif letter == 75:
print("C")
break
elif 70 <= letter <= 74:
print("C-")
break
elif 65 < letter <= 69:
print("D+")
break
elif letter == 65:
print("D")
break
elif 60 <= letter <= 64:
print("D-")
break
elif letter <= 59:
print("F")
break
def call_functions(): # This takes all the definitions and makes it into one definition
student()
preparation_assignment_average()
lab_score_average()
post_lab_average()
exam_average()
overall_weighted_class_average()
letter_grade_for_class()
return ''
# After computing all the averages for the line of data it then writes it to a new file
original_stdout = sys.stdout
with open('test_file.csv', 'a') as file:
sys.stdout = file
for i in call_functions():
file.writelines('\n%s' % i)
sys.stdout = original_stdout
except ValueError: # displays when one of the letters is out of its index
print('Sorry, one of the letters in the file is out of place. Please check the file again to make sure that \n'
'the letter is not where the numbers are supposed to be. Check indexes 29-39. That is where the \n'
'letter grades for the file should be.')
exit(1)
except FileNotFoundError: # displays error if there is no file by that name
print("Sorry, the current file that you have selected is not a File.")
exit(1)
except IndexError: # this displays when there is no data in the file
print('The file that you have selected does not contain any grades. Please check the file again.')
exit(1)
except PermissionError: # this displays when you have the file open
print('The file that you are trying to open is already open. Close the file and restart the program.')
exit(1)
if __name__ == "__main__":
main()
您好,我对使用 python 编辑 csv 文件有点陌生。我正在做一个项目。这是一个简单的成绩计算器,可读取名为 new_grade.csv 的 csv 文件。我的脚本计算每个学生的平均成绩。我不小心对我的脚本进行了硬编码,并且在读取多个 csv 行时遇到了问题。 我的问题是如何将我的代码修改为 运行 任意一行数据。我的代码只处理第一行数据。任何帮助将不胜感激。
我的 csv 文件:
Smithy, James, 100, 78, 92, 92, 85, 85, 95, 100, 75, 85, 50, 85, 87, 95, 95, 80, 80, 96, 95, 95, 95, 85, 79, 95, 85, 95, A, A+, A, B, A+, F, C, B, A, A, A, A, 85, 95, 82, 91
Gadget, John, 0, 0, 92, 92, 85, 60, 85, 100, 75, 85, 50, 85, 0, 95, 85, 70, 70, 0, 95, 95, 95, 85, 0, 95, 0, 95, F, F, F, B, A+, A, C, B, C, F, F, F, 45, 75, 82, 31
Phillips, David, 100, 78, 92, 92, 85, 90, 85, 100, 75, 85, 50, 85, 87, 95, 85, 80, 80, 96, 95, 95, 95, 85, 79, 95, 85, 95, A, A+, A, B, A+, A, A, B, C, A, A, A, 85, 95, 82, 91
我的一行数据能解决的代码:
def main():
try:
import csv
import sys
# This section opens up the file grades.csv. It will then read the data and then takes that data and converts
# that data into a list. When it's in a list we can splice the data to compute averages.
with open("new_grade.csv", 'r') as f:
list(csv.reader(f)) # had data = variable
while True:
# function to remove \n character from csv file
def remove_newlines(fname):
flist = open(fname).readlines()
return [s.rstrip('\n') for s in flist]
old_line = (remove_newlines("new_grade.csv"))
# For required output:
line = old_line[0].split(', ') # This open up the line of the file. For instance this opens up line 1 of
# file.
if len(line) > 44: # This checks to make sure that the data doesn't exceed 44 indexes
print('The data in your file exceeds the maximum amount. Check line 1 of your file. ')
sys.exit(1)
def student():
print((line[0]) + ',' + ' ' + (line[1]), end=', ') # This finds the student's name
def preparation_assignment_average(): # This will compute the preparation assignment average.
global prep
prep = 0
for i in (line[2:16]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
prep = prep + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
sys.exit(1) # This ends the program if it fails the if statement
print(round((prep / 14), 2), end=', ')
def lab_score_average(): # This will compute the lab score average
global lab
lab = 0
for i in (line[17:28]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
lab = lab + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
sys.exit(1) # This ends the program if it fails the if statement
print(round((lab / 12), 2), end=', ')
def post_lab_average(): # This calculates the post lab average of the student. It takes a letter and
# converts the letter to a score that is an integer.
global score
score = 0
for i in (line[28:39]):
if i == "A+":
score += 100
elif i == "A":
score += 95
elif i == "A-":
score += 90
elif i == "B":
score += 85
elif i == "C":
score += 75
elif i == "D":
score += 60
elif i == "F":
score += 0
elif i is not "A+" or "A" or "A-" or "B" or "C" or "D" or "F":
print('Your file is not formatted to the standard of the program. On line 1 of your file, '
'you have\na score where a letter grade should be. Please check file and rerun the '
'program.')
sys.exit(1)
print(round((score / 12), 2), end=', ')
def exam_average(): # This will compute the exam average for the student
global exam
exam = 0
for i in (line[40:44]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
exam = exam + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
sys.exit(1) # This ends the program if it fails the if statement
print(round((exam / 4), 2), end=', ')
def overall_weighted_class_average(): # This will compute the overall class average for the student
global weighted_class_grade
global weighted_prep
global weighted_lab
global weighted_score
global weighted_exam
weighted_prep = ((prep / 14) * .10) # This is calculating the weighted average for a
weighted_lab = ((lab / 12) * .20) # This is calculating the weighted average for b
weighted_score = ((score / 12) * .10) # This is calculating the weighted average for score
weighted_exam = ((exam / 4) * .60) # This is calculating the weighted average for exam
weighted_class_grade = round((weighted_prep + weighted_lab + weighted_score + weighted_exam), 2)
print(weighted_class_grade, end=', ')
def letter_grade_for_class(): # This will take the weighted class grade and it will print that grade
# according to the range
letter = weighted_class_grade
while True:
if 95 < letter <= 100:
print("A+")
break
elif letter == 95:
print("A")
break
elif 90 <= letter <= 94:
print("A-")
break
elif 85 < letter <= 89:
print("B+")
break
elif letter == 85:
print("B")
break
elif 80 <= letter <= 84:
print("B-")
break
elif 75 < letter <= 79:
print("C+")
break
elif letter == 75:
print("C")
break
elif 70 <= letter <= 74:
print("C-")
break
elif 65 < letter <= 69:
print("D+")
break
elif letter == 65:
print("D")
break
elif 60 <= letter <= 64:
print("D-")
break
elif letter <= 59:
print("F")
break
def call_functions(): # This takes all the definitions and makes it into one definition
student()
preparation_assignment_average()
lab_score_average()
post_lab_average()
exam_average()
overall_weighted_class_average()
letter_grade_for_class()
return ''
break
# After computing all the averages for the line of data it then writes it to a new file
original_stdout = sys.stdout
file = open('test_file.csv', 'x') # The x will not save the file if it already exists
sys.stdout = file
for i in call_functions():
file.writelines('\n%s' % i)
sys.stdout = original_stdout
file.close()
f.close()
except ValueError: # displays when one of the letters is out of its index
print('Sorry, one of the letters in the file is out of place. Please check the file again to make sure that \n'
'the letter is not where the numbers are supposed to be. Check indexes 29-39. That is where the \n'
'letter grades for the file should be.')
sys.exit(1)
except FileNotFoundError: # displays error if there is no file by that name
print("Sorry, the current file that you have selected is not a File.")
sys.exit(1)
except IndexError: # this displays when there is no data in the file
print('The file that you have selected does not contain any grades. Please check the file again.')
sys.exit(1)
except PermissionError:
print('The file that you are trying to save is already a file. The file is protected and can not be written.')
sys.exit(1)
except FileExistsError:
print('The file that you are trying to save is already a file. Please rename your file or delete that file '
'and rerun the program.')
sys.exit(1)
if __name__ == "__main__":
main()
我认为有两件事可以解释您所看到的行为并提示您可以修改代码的方式。
行
line = old_line[0].split(', ')
表示您只阅读文件的第一行。你应该有某种循环访问文件的每一行作为line = old_line[index].split(',')
.下面的循环可能并没有按照您的想法进行:
for i in call_functions():
file.writelines('\n%s' % i)
sys.stdout = original_stdout
file.close()
call_functions()
方法实际上 returns 一个空字符串,所以这个循环的主体实际上根本没有 运行。 call_functions()
只调用一次,这就是您在输出 csv 中只看到一行输出的原因。您需要为 CSV 中的每一行调用 call_functions()
。
这篇文章很长 post 所以我将把它分成几部分,以提高可读性。完整代码在更改说明之后。
第一部分
我复制并粘贴了您的代码,PyCharm 和 Visual Studio 在第 72 行为您的 post_lab_average()
函数捕获了 SyntaxWarning 错误。
这是触发它的 elif
语句:
elif i is not "A+" or "A" or "A-" or "B" or "C" or "D" or "F":
该程序只是希望您将 is not
更改为 !=
,但老实说,您在这里不需要表达式,因为您已经要检查所有其他字母了。你真的只需要 else:
而不是 elif i != 'A+' or 'A' or ...
在进行了我将要解释的所有其他更改后,程序 运行 在本节中再次出现问题,其中 if i == "A+":
如果有额外的 space 将无法工作它正在检查的行,即 i = " A+"
。为了解决这个问题,我们将表达式改写为 if "A+" in i:
,这样我们就可以检查 "A+"
,而不管是否有额外的 space。
您的 post_lab_average()
应该如下所示:
def post_lab_average():
global score
score = 0
for i in (line[28:39]):
if "A+" in i:
score += 100
elif "A" in i:
score += 95
elif "A-" in i:
score += 90
elif "B" in i:
score += 85
elif "C" in i:
score += 75
elif "D" in i:
score += 60
elif "F" in i:
score += 0
else:
print('Your file is not formatted to the standard of the program. On line 1 of your file, '
'you have\na score where a letter grade should be. Please check file and rerun the '
'program.')
exit(1)
此外,在您调用 sys.exit(1)
终止程序的整个代码中,sys.
是不必要的,仅使用 exit(1)
即可。
第二部分
接下来弹出的错误是异常,FileExistsError
为行
file = open('test_file.csv', 'x')
最后,我们会将数据附加到 csv 文件中,因此我们将在 main()
函数的开头包含这行代码:
import os
try:
os.remove('test_file.csv')
except FileNotFoundError:
pass
这将始终删除文件(如果存在),您可以在最后删除 except FileExistsError:
,因为异常将不再触发。
第三部分
当使用 with open()
打开文件时,默认设置是读取文件,因此您不需要添加 'r'
您实际上不需要 remove_newlines()
函数,我们'将打开文件并将数据分配给列表,如下所示:
with open('new_grade.csv') as file:
student_list = list(csv.reader(file))
第四部分
现在我们将使用计数器将您的 while True
循环调整为 运行,当所有列表达到 运行 时停止。
count = 0
while count < len(student_list):
line = student_list[count]
count += 1
循环将继续,直到 运行 遍历了 student_list
中的所有子列表。您必须在循环结束时摆脱您的 break
才能正常工作。
第五部分
快完成了! 运行 当前状态下的文件将生成一个仅包含条目中最后一名学生的文件。为了解决这个问题,我们将缩进写入文件的代码块,以便它 运行 在每个循环结束时而不是在循环结束后。我还重新格式化为使用 with open('a')
这样我们就可以附加我们的数据而不是覆盖。
original_stdout = sys.stdout
with open('test_file.csv', 'a') as file:
sys.stdout = file
for i in call_functions():
file.writelines('\n%s' % i)
sys.stdout = original_stdout
最终代码
def main():
try:
import csv
import sys
import os
# Checks if file exists and removes it if found
try:
os.remove('test_file.csv')
except FileNotFoundError:
pass
# Opens the data file and assigns it to a list
with open('new_grade.csv') as file:
student_list = list(csv.reader(file))
# Loops through each student in list
count = 0
while count < len(student_list):
line = student_list[count]
count += 1
if len(line) > 44: # This checks to make sure that the data doesn't exceed 44 indexes
print('The data in your file exceeds the maximum amount. Check line 1 of your file. ')
sys.exit(1)
def student():
print((line[0]) + ',' + ' ' + (line[1]), end=', ') # This finds the student's name
def preparation_assignment_average(): # This will compute the preparation assignment average.
global prep
prep = 0
for i in (line[2:16]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
prep = prep + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
exit(1) # This ends the program if it fails the if statement
print(round((prep / 14), 2), end=', ')
def lab_score_average(): # This will compute the lab score average
global lab
lab = 0
for i in (line[17:28]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
lab = lab + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
exit(1) # This ends the program if it fails the if statement
print(round((lab / 12), 2), end=', ')
def post_lab_average(): # This calculates the post lab average of the student. It takes a letter and
# converts the letter to a score that is an integer.
global score
score = 0
for i in (line[28:39]):
if "A+" in i:
score += 100
elif "A" in i:
score += 95
elif "A-" in i:
score += 90
elif "B" in i:
score += 85
elif "C" in i:
score += 75
elif "D" in i:
score += 60
elif "F" in i:
score += 0
else:
print('Your file is not formatted to the standard of the program. On line 1 of your file, '
'you have\na score where a letter grade should be. Please check file and rerun the '
'program.')
exit(1)
print(round((score / 12), 2), end=', ')
def exam_average(): # This will compute the exam average for the student
global exam
exam = 0
for i in (line[40:44]):
i = int(i)
if 0 <= i <= 100: # This is checking to make sure that the grades are in the range 0-100
exam = exam + int(i)
else: # if it is not in the range of 0-100 it will print this statement and end the program
print('One of the values that you entered is not valid. Please enter a grade within the '
'range 0-100, Error\noccurred on line 1 in text file.')
exit(1) # This ends the program if it fails the if statement
print(round((exam / 4), 2), end=', ')
def overall_weighted_class_average(): # This will compute the overall class average for the student
global weighted_class_grade
global weighted_prep
global weighted_lab
global weighted_score
global weighted_exam
weighted_prep = ((prep / 14) * .10) # This is calculating the weighted average for a
weighted_lab = ((lab / 12) * .20) # This is calculating the weighted average for b
weighted_score = ((score / 12) * .10) # This is calculating the weighted average for score
weighted_exam = ((exam / 4) * .60) # This is calculating the weighted average for exam
weighted_class_grade = round((weighted_prep + weighted_lab + weighted_score + weighted_exam), 2)
print(weighted_class_grade, end=', ')
def letter_grade_for_class(): # This will take the weighted class grade and it will print that grade
# according to the range
letter = weighted_class_grade
while True:
if 95 < letter <= 100:
print("A+")
break
elif letter == 95:
print("A")
break
elif 90 <= letter <= 94:
print("A-")
break
elif 85 < letter <= 89:
print("B+")
break
elif letter == 85:
print("B")
break
elif 80 <= letter <= 84:
print("B-")
break
elif 75 < letter <= 79:
print("C+")
break
elif letter == 75:
print("C")
break
elif 70 <= letter <= 74:
print("C-")
break
elif 65 < letter <= 69:
print("D+")
break
elif letter == 65:
print("D")
break
elif 60 <= letter <= 64:
print("D-")
break
elif letter <= 59:
print("F")
break
def call_functions(): # This takes all the definitions and makes it into one definition
student()
preparation_assignment_average()
lab_score_average()
post_lab_average()
exam_average()
overall_weighted_class_average()
letter_grade_for_class()
return ''
# After computing all the averages for the line of data it then writes it to a new file
original_stdout = sys.stdout
with open('test_file.csv', 'a') as file:
sys.stdout = file
for i in call_functions():
file.writelines('\n%s' % i)
sys.stdout = original_stdout
except ValueError: # displays when one of the letters is out of its index
print('Sorry, one of the letters in the file is out of place. Please check the file again to make sure that \n'
'the letter is not where the numbers are supposed to be. Check indexes 29-39. That is where the \n'
'letter grades for the file should be.')
exit(1)
except FileNotFoundError: # displays error if there is no file by that name
print("Sorry, the current file that you have selected is not a File.")
exit(1)
except IndexError: # this displays when there is no data in the file
print('The file that you have selected does not contain any grades. Please check the file again.')
exit(1)
except PermissionError: # this displays when you have the file open
print('The file that you are trying to open is already open. Close the file and restart the program.')
exit(1)
if __name__ == "__main__":
main()