Зачем генерировать ValueError с помощью int () для чтения частей строк из файла .txt? - PullRequest
0 голосов
/ 26 сентября 2018

Это подпрограмма, которая читает из 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:] включает символ новой строки, который ломает int().Но использование line[line.find('|') + 1:line.find('\\')] не решает проблему - выдается та же ошибка.

Ответы [ 3 ]

0 голосов
/ 26 сентября 2018

Более простой подход.

Демонстрация:

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)
0 голосов
/ 26 сентября 2018

Здесь:

while line != '':
    line = test_results_file.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, однако он завершается (независимо от того, завершился ли цикл for или является исключением).случилось).

Кроме того, вместо того, чтобы делать сложные вычисления, чтобы найти деталь после канала, вы можете просто разбить вашу строку:

for line in test_results_file:
    total = int(line.strip().split("|")[1])
     num_recs += 1

И, наконец, вы можете использовать * 1028 stdlib's* модуль для анализа вашего файла вместо того, чтобы делать это вручную ...

0 голосов
/ 26 сентября 2018

Потому что это не числовое значение.Итак, 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)

readlines против readline

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

Если мы используем readlines, то он вернет список, основанный на\n символ.

readline

Из приведенного выше кода мы можем видеть, что у нас есть только 3 строки в stringIO, но когда мы получаем доступ к readline, он всегда дает нам пустую строку,Итак, в вашем коде вы конвертируете его в целое число, из-за чего вы получаете исключение ValueError.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...