Необходимо использовать функции seek (), tell (), next () и readline () - PullRequest
0 голосов
/ 03 мая 2018

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

Чтобы упростить мой вопрос, допустим, что я хочу читать элементы файла 1, 3 на 3 и файла 2 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(). Теперь мой вопрос: как я могу расположить свой скрипт так, чтобы он выглядел одинаково, не используя много памяти?

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

1 Ответ

0 голосов
/ 03 мая 2018

Так как вам нужно только читать файлы последовательно, вы можете использовать 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)
...