Необходимо использовать функции seek (), tell (), next () и readline () вместе

В моем случае у меня есть два файла csv (file1 и file2).

Чтобы упростить мой вопрос, скажем, что я хочу последовательно читать элементы file1, 3 на 3 и file2 4 на 4.

file1.csv (9 строка)

1,2,3
3,5,8
7,2,9
10,111,12
13,14,155
31,2,3
3,15,82
8,4,91
12,111,13

file2.csv (12 строк)

55,12,17
3,6,13
72,1,91
10,0,12
1,1,73
31,2,3
3,15,61
18,6,91
13,33,13
7,1,15
9,17,42
41,8,18

на выходе я хочу получить:

1,2,3 (from 1. row of file1.csv)
3,5,8 (from 2. row of file1.csv)
7,2,9 (from 3. row of file1.csv)
55,12,17  (from 1. row of file2.csv)
3,6,13  (from 2. row of file2.csv)
72,1,91  (from 3. row of file2.csv)
10,0,12  (from 4. row of file2.csv)
10,111,12  (from 4. row of file1.csv)
13,14,155  (from 5. row of file1.csv)
31,2,3  (from 6. row of file1.csv)
1,1,73  (from 5. row of file2.csv)
31,2,3  (from 6. row of file2.csv)
3,15,61  (from 7. row of file2.csv)
18,6,91  (from 8. row of file2.csv)
3,15,82  (from 7. row of file1.csv)
8,4,91  (from 8. row of file1.csv)
12,111,13  (from 9. row of file1.csv)
13,33,13  (from 9. row of file2.csv)
7,1,15  (from 10. row of file2.csv)
9,17,42  (from 11. row of file2.csv)
41,8,18  (from 12. row of file2.csv)

Мои настоящие файлы данных очень большие (~ 1,6 ГБ каждый), и я хочу использовать как можно меньше памяти. Для этого я написал сценарий:

f1, f2, = open(pathInput1, 'r'), open(pathInput2, 'r')
position1, position2 = 0, 0

for i in range(6):
    if i%2 == 0:
        #print("file1.csv")
        sizeOfWindow = 3
        sizeOfWindowInactive = 4
        f1.seek(position1)
        data = []
        for l in range(sizeOfWindow):
            line = f1.readline()
            line = list(map(int, line[:-1].split(",")))
            data.append(line)
        data = np.array(data)
        print(data)
        [next(f2) for i in range(sizeOfWindowInactive)]
        position1 = f1.tell()
    else:
        #print("file2.csv")
        sizeOfWindow = 4
        sizeOfWindowInactive = 3
        f2.seek(position2)
        data = []
        for l in range(sizeOfWindow):
            line = f2.readline()
            line = list(map(int, line[:-1].split(",")))
            data.append(line)
        data = np.array(data)
        print(data)
        [next(f1) for i in range(sizeOfWindowInactive)]
        position2 = f2.tell()

Написав этот скрипт, я заметил, что не могу использовать одновременно readline() и next(). Теперь мой вопрос: как я могу организовать свой сценарий, чтобы он наблюдал тот же результат, не используя много памяти.

Изменить: в моем реальном случае у меня есть 5 файлов, и каждый файл имеет свой sizeOfWindow. В зависимости от данных, которые я прочитал, я решаю перейти к файлам с помощью оператора if. Итак, sizeOfWindow фиксируется в зависимости от файлов. Я не читаю файлы регулярно. Я решаю, что файл переместится, используя последнюю часть данных, которую я прочитал. Когда я читаю файл, мне нужно переместить курсор других файлов, не читая их данные.


person Mas A    schedule 03.05.2018    source источник
comment
Чтобы усложнить задачу, вы не можете надежно использовать seek и tell в небинарном файле (строковый декодер мешает). Если вы просто хотите чередовать строки, этот уровень сложности вам не нужен.   -  person tdelaney    schedule 03.05.2018
comment
Я не вижу в этом проблемы. У каждого файлового дескриптора есть своя закладка. Вы читаете 3 строки из file1, затем читаете 4 строки из file2. Вы читаете каждый файл по порядку: нет необходимости в seek, next, или tell. Повторяйте, пока в файлах не закончатся данные.   -  person Prune    schedule 03.05.2018
comment
выбросьте поиски и взгляды - просто прочтите 3 строки здесь, 4 строки там, повторите - может быть, событие лучше (спросите numpycracks) - прочтите бота на разные повествования и чередуйте их там. Не знаю, насколько хороша эта память, но если все, что вы хотите сделать, это распечатать их на консоли, вам не нужно 80% вашего кода, поскольку не имеет значения, печатаете ли вы их как строку (как прочитанную из файла) или анализируете / en -спишите их перед печатью ...   -  person Patrick Artner    schedule 03.05.2018
comment
@tdelaney, я нашел это здесь, они используют stackoverflow.com/questions/15594817/   -  person Mas A    schedule 03.05.2018
comment
@Prune нет, использование next и readline является проблемой. Комбинирование метода next () с другими файловыми методами, такими как readline (), не работает. Однако использованиеseek () для перемещения файла в абсолютное положение очистит буфер упреждающего чтения. tutorialspoint.com/python/file_next.htm   -  person Mas A    schedule 03.05.2018
comment
@Patricks Artner спасибо, но это сложнее   -  person Mas A    schedule 03.05.2018
comment
@SmA: Я пропустил один: вы выбрасываете либо next, либо readline.   -  person Prune    schedule 03.05.2018
comment
Вы говорите, что когда я читаю файл, мне нужно переместить курсор других файлов, не читая их данные. Почему? Ваш опубликованный желаемый результат явно читает все данные в обоих файлах по порядку.   -  person Prune    schedule 03.05.2018


Ответы (1)


Поскольку вам нужно только читать файлы последовательно, вы можете использовать next(f1) и next(f2) по мере необходимости, чтобы получить нужные строки. Модуль itertools содержит помощники, которые упрощают эту задачу. itertools.islice захватит несколько строк, поэтому вам не нужен собственный цикл для next. И itertools.cycle будет чередовать элементы в списке, поэтому вам не нужно отслеживать, какой файл будет следующим. Собираем вместе:

import itertools
import numpy as np

with open(pathInput1) as f1, open(pathInput2) as f2:
    grab_this = ((3, f1), (4, f2))
    for num, fp in itertools.cycle(grab_this):
        data = np.array(itertools.islice(fp, num))
        if not data:
            break
        print(data)
person tdelaney    schedule 03.05.2018
comment
Не могли бы вы прочитать мою правку сверху. Спасибо, но я уже пробовал islice(), и он отнимает у меня много памяти. У вас есть другое предложение? - person Mas A; 03.05.2018
comment
когда я попробовал ваш код, он выдает ошибку: data = np.array (itertools.islice (fp, num)) ValueError: Стоп-аргумент для islice() должен быть None или целым числом: 0 ‹= x‹ = sys.maxsize. (я использовал islice() вот так: for line in islice(f1, sizeOfWindowInactive, None): pass, чтобы пропустить ненужные строки. Как я уже сказал, мне потребовалось больше памяти, я не знаю почему - person Mas A; 03.05.2018
comment
Виноват. Это должно было быть itertools.cycle. Код выполнял эквивалент islice((4, f2), (3, f1)), и этот второй параметр определенно не является целым числом! islice(f1, sizeOfWindowInactive, None) - это тоже не то, что вам нужно - он использует весь итератор. Я изменил код, и он должен работать намного лучше. - person tdelaney; 04.05.2018