По-добър подход за четене/запис на файлове в python?

Да предположим, че имам файл (да кажем file1.txt) с данни около 3mb или повече. Ако искам да запиша тези данни във втори файл (да речем file2.txt), кой от следните подходи ще бъде по-добър?

Използван език: Python 2.7.3

Подход 1:

file1_handler = file("file1.txt", 'r')
for lines in file1_handler:
    line = lines.strip()
    # Perform some operation
    file2_handler = file("file2.txt", 'a')
    file2_handler.write(line)
    file2_handler.write('\r\n')
    file2_handler.close()
file1_handler.close()

Подход 2:

file1_handler = file("file1.txt", 'r')
file2_handler = file("file2.txt", 'a')
for lines in file1_handler:
    line = lines.strip()
    # Perform some operation
    file2_handler.write(line)
    file2_handler.write('\r\n')
file2_handler.close()
file1_handler.close()

Мисля, че подход две ще бъде по-добър, защото просто трябва да отворите и затворите file2.txt веднъж. Какво казваш?


person Hemant    schedule 20.03.2013    source източник
comment
Отворете файл с open, а не с файл.   -  person Matthias    schedule 20.03.2013


Отговори (3)


Използвайте with, той автоматично ще затвори файловете вместо вас:

with open("file1.txt", 'r') as in_file, open("file2.txt", 'a') as out_file:
    for lines in in_file:
        line = lines.strip()
        # Perform some operation
        out_file.write(line)
        out_file.write('\r\n')

Използвайте open вместо file, file е отхвърлено.

Разбира се, неразумно е да се отваря file2 на всеки ред от file1.

person Pavel Anossov    schedule 20.03.2013
comment
Пишех същата мисъл :) @Hemant, вижте: docs.python.org/2/whatsnew/2.5.html#pep-343-the-with-statement - person Francesco Frassinelli; 20.03.2013
comment
Относно f2.write('\r\n'): за да направите това, трябва да отворите f2 като двоичен файл (прибавяйки b към флага). - person Francesco Frassinelli; 20.03.2013
comment
опа! Мислех, че open е остарял :p (не прочетох документите правилно), така че скоростта на писане се увеличава? Тъй като първият подход отнемаше почти 2 часа за копиране на 1 MB данни. - person Hemant; 20.03.2013
comment
@Francesco: можете ли да обясните малко за този подход на двоичен файл? - person Hemant; 20.03.2013
comment
@Hemant: погледнете: Вижте: stackoverflow.com/questions/2536545/ Ако пишете \n без двоичен режим, Python ще използва по-подходящия краен ред за вашата платформа. Ако искате да използвате конкретен краен ред, трябва да използвате двоичния флаг. - person Francesco Frassinelli; 20.03.2013
comment
Това важи само за Windows. Python в Windows прави разлика между текстови и двоични файлове; знаците в края на реда в текстовите файлове автоматично се променят леко, когато данните се четат или записват. - person Pavel Anossov; 20.03.2013
comment
@Hemant: бихте могли да обмислите внедряването на буфер, за да направите чифт големи записи, а не много малки. Можете просто да добавите вашите редове към списък и, когато списъкът е доста голям, да ги напишете всички. - person Francesco Frassinelli; 20.03.2013
comment
@Francesco: причината да използвам '\r\n' е, че искам да въведа следващия ред от файл1 на следващия ред от файл2. прави ли двоичният режим това или просто запазва '\r\n' както е? - person Hemant; 20.03.2013
comment
@Hemant: да. \r\n е за Windows, на Linux/Mac имате \n. Ако сте на Linux и искате да пишете като Windows (например), трябва да използвате двоичния режим и да пишете \r\n. - person Francesco Frassinelli; 20.03.2013
comment
@Francesco: Ще се опитам да приложа този буферен подход :) - person Hemant; 20.03.2013
comment
Двоичният режим няма ефект върху Unix. Пише това, което му е казано да напише. - person Pavel Anossov; 20.03.2013
comment
@Francesco: Не те разбирам.. твоето „да“ е за кой отговор? конвертиране в новия ред или писане на '\r\n' както си е? - person Hemant; 20.03.2013
comment
Текстовият режим в Windows преобразува \r и \n в \r\n. \r\n остава непроменено. - person Pavel Anossov; 20.03.2013
comment
@PavelAnossov благодаря за информацията. Хемант: Павел Аносов отговори правилно :) - person Francesco Frassinelli; 20.03.2013

Наскоро правех нещо подобно (ако съм те разбрал добре). Какво ще кажеш:

file = open('file1.txt', 'r')
file2 = open('file2.txt', 'wt')

for line in file:
  newLine = line.strip()

  # You can do your operation here on newLine

  file2.write(newLine)
  file2.write('\r\n')

file.close()
file2.close()

Този подход работи като чар!

person Oscar_Mariani    schedule 20.03.2013

Моето решение (извлечено от Павел Аносов + буфериране):

dim = 1000
buffer = []
with open("file1.txt", 'r') as in_file, open("file2.txt", 'a') as out_file:
    for i, lines in enumerate(in_file):
        line = lines.strip()
        # Perform some operation
        buffer.append(line)
        if i%dim == dim-1:
            for bline in buffer:
                out_file.write(bline)
                out_file.write('\r\n')
            buffer = []

Павел Аносов първо даде правилното решение: това е само предложение ;) Вероятно съществува по-елегантен начин за реализиране на тази функция. Ако някой го знае, моля да ни каже.

person Francesco Frassinelli    schedule 20.03.2013
comment
@ Francesco: Хей, благодаря за този отговор :), но не съм много запознат с метода за изброяване. Можете ли да ми обясните предимствата от използването на enumerate? - person Hemant; 21.03.2013
comment
@Hemant: enumerate е полезно :) Виж тук: docs.python.org/2 /library/functions.html#enumerate - person Francesco Frassinelli; 21.03.2013
comment
@ Francesco: благодаря за документа. сега разбирам примера ти по-ясно. :) - person Hemant; 21.03.2013