Это подпрограмма, которая читается из studentNamesfile.txt
def calculate_average():
'''Calculates and displays average mark.'''
test_results_file = open('studentNamesfile.txt', 'r')
total = 0
num_recs = 0
line = ' '
while line != '':
line = test_results_file.readline()
# Convert everything after the delimiting pipe character to an integer, and add it to total.
total += int(line[line.find('|') + 1:])
num_recs += 1
test_results_file.close()
[ num_recs
содержит количество записей, считанных из файла.]
Формат studentNamesfile.txt
выглядит следующим образом:
Student 01|10
Student 02|20
Student 03|30
и так далее. Эта подпрограмма предназначена для чтения метки всех записей студента в файле, но я получаю эту ошибку при ее запуске:
Traceback (most recent call last):
File "python", line 65, in <module>
File "python", line 42, in calculate_average
ValueError: invalid literal for int() with base 10: ''
Эта ошибка довольно ясна, но я не могу понять, почему ее бросают. Я пробовал отслеживать значение line[line.find('|') + 1:]
, но Python утверждает, что он имеет правильное значение (например, 10), когда я использую print(line[line.find('|') + 1:]
на предыдущей строке. Что случилось?
Обновление: я рассматриваю возможность того, что line[line.find('|') + 1:]
включает в себя новую line[line.find('|') + 1:]
которая line[line.find('|') + 1:]
int()
. Но использование line[line.find('|') + 1:line.find('\\')]
не устраняет проблему - возникает line[line.find('|') + 1:line.find('\\')]
та же ошибка.
Вот:
while line != '':
line = test_results_file.readline()
Когда вы попадаете в конец файла, .readline()
возвращает пустую строку, но так как это происходит после .readline()
while line != ''
, Вы все равно пытаетесь обработать эту строку.
Канонический (и гораздо более простой) способ перебора файла по строкам, который должен, ну, итерации по файлу, избежать этой проблемы:
for line in test_result_file:
do_something_with(line)
Вам просто нужно позаботиться о вызове .rstrip()
в line
если вы хотите избавиться от символа окончания новой строки (что соответствует вашему коду).
Кроме того, вы хотите убедиться, что файл правильно закрыт, что происходит. Канонический способ - использовать open()
в качестве менеджера контекста:
with open("path/to/file.txt") as f:
for line in test_result_file:
do_something_with(line)
Это вызовет f.close()
при выходе из блока with
, однако он f.close()
только что закончен цикл for или произошло исключение).
Кроме того, вместо выполнения сложных вычислений, чтобы найти деталь после трубы, вы можете просто разделить строку:
for line in test_results_file:
total = int(line.strip().split("|")[1])
num_recs += 1
И, наконец, вы можете использовать модуль stdlib csv
для анализа вашего файла вместо того, чтобы делать это вручную...
Потому что это не числовое значение. Таким образом, python бросает ValueError
если он не способен преобразовать его в целое. Вы можете под кодом, чтобы проверить его.
def calculate_average():
test_results_file = open('studentNamesfile.txt', 'r')
total = 0
num_recs = 0
for line in test_results_file.readlines():
try:
total += int(line[line.find('|') + 1:])
num_recs += 1
except ValueError:
print("Invalid Data: ", line[line.find('|') + 1:])
test_results_file.close()
print("total:", total)
print("num_recs:", num_recs)
print("Average:", float(total)/num_recs)
from io import StringIO
s = 'hello\n hi\n how are you\n'
f = StringIO(unicode(s))
l = f.readlines()
print(l)
# OUTPUT: [u'hello\n', u' hi\n', u' how are you\n']
f = StringIO(unicode(s))
l1 = f.readline()
# u'hello\n'
l2 = f.readline()
# u' hi\n'
l3 = f.readline()
# u' how are you\n'
l4 = f.readline()
# u''
l5 = f.readline()
# u''
Если мы используем readlines
тогда он вернет список на основе символа \n
.
Из кода выше видно, что у нас есть только 3 строки в stringIO
но когда мы получаем доступ к readline
он всегда дает нам пустую строку. поэтому в коде вы преобразуете его в целое число, потому что вы получаете исключение ValueError
.
except
никогда не выполняется - оно работает! Вы изменили способ чтения файла?
for line in test_results_file.readlines():
Пожалуйста, примите ответ и проголосуйте.
Более простой подход.
Демо - версия:
total = 0
num_recs = 0
with open(filename) as infile: #Read File
for line in infile: #Iterate Each line
if "|" in line: #Check if | in line
total += int(line.strip().split("|")[-1]) #Extract value and sum
num_recs += 1
print(total, num_recs)