Ответ 1
rows = list(myreader)
totalrows = len(rows)
for i, row in enumerate(rows):
print("Row %d/%d" % (i+1, totalrows))
У меня есть объект csv DictReader (с использованием Python 3.1), но я хотел бы знать количество строк/строк, содержащихся в считывателе до. Я повторяю его. Что-то вроде следующего...
myreader = csv.DictReader(open('myFile.csv', newline=''))
totalrows = ?
rowcount = 0
for row in myreader:
rowcount +=1
print("Row %d/%d" % (rowcount,totalrows))
Я знаю, что могу получить общее количество, повторяя через читателя, но тогда я не смог запустить цикл "за". Я мог перебирать копию читателя, но я не могу найти, как копировать итератор.
Я мог бы также использовать
totalrows = len(open('myFile.csv').readlines())
но это кажется ненужным повторным открытием файла. Я предпочел бы получить счетчик из DictReader, если это возможно.
Любая помощь будет оценена.
Алан
rows = list(myreader)
totalrows = len(rows)
for i, row in enumerate(rows):
print("Row %d/%d" % (i+1, totalrows))
Вам нужно только открыть файл один раз:
import csv
f = open('myFile.csv', 'rb')
countrdr = csv.DictReader(f)
totalrows = 0
for row in countrdr:
totalrows += 1
f.seek(0) # You may not have to do this, I didn't check to see if DictReader did
myreader = csv.DictReader(f)
for row in myreader:
do_work
Независимо от того, что вы делаете, вам нужно сделать два прохода (ну, если ваши записи фиксированной длины - что маловероятно - вы можете просто получить размер файла и разделить, но давайте предположим, что это не так). Открытие файла снова действительно не стоит вам дорого, но вы можете избежать его, как показано здесь. Преобразование в список только для использования len()
потенциально собирается тратить массу памяти, а не быть быстрее.
Примечание. Путь "Pythonic" заключается в использовании enumerate
вместо +=
, но код операции UNPACK_TUPLE
настолько дорог, что он enumerate
медленнее, чем приращение локального. Это, как говорится, вероятно, является ненужной микро-оптимизацией, которую вы, вероятно, должны избегать.
Дополнительные примечания. Если вы действительно хотите создать какой-то индикатор прогресса, он не обязательно должен быть основан на записи. Вы можете tell()
в файловом объекте в цикле и просто сообщить, сколько% данных вы прошли. Это будет немного неравномерно, но шансы на любой файл, который достаточно велик, чтобы гарантировать прогресс, отклонение от длины записи будет потеряно в шуме.
Я не могу найти, как скопировать итератор.
Ближайший itertools.tee, но просто делая list
этого, как предлагает @JFSebastian, лучше всего здесь, так как itertools.tee docs объясняет:
Этот itertool может потребовать значительных вспомогательное хранилище (в зависимости от того, как много временных данных сохранены). В общем случае, если один итератор использует большинство или все данные до другой итератор запускается, он быстрее для использования
list()
вместоtee()
.