Сохраняет ли функция «открытия» Python свой контент в памяти или во временном файле? - PullRequest
8 голосов
/ 10 февраля 2010

Для следующего кода Python:

fp = open('output.txt', 'wb')
# Very big file, writes a lot of lines, n is a very large number
for i in range(1, n):
    fp.write('something' * n)
fp.close()

Процесс написания выше может длиться более 30 минут. Иногда я получаю ошибку MemoryError. Содержимое файла перед закрытием сохраняется в памяти или записывается во временный файл? Если он находится во временном файле, каково его общее расположение в ОС Linux?

Edit:

Добавлен fp.write в цикле for

Ответы [ 6 ]

5 голосов
/ 10 февраля 2010

Он хранится в кэш-памяти операционной системы в памяти до тех пор, пока не будет сброшен на диск, либо неявно из-за проблем с синхронизацией или нехваткой места, либо явно через fp.flush().

3 голосов
/ 10 февраля 2010

В ядре Linux будет буферизация записи, но через (ир) регулярные интервалы они будут сбрасываться на диск. Нехватка такого буферного пространства никогда не должна вызывать ошибку памяти уровня приложения; буферы должны очиститься до того, как это произойдет, приостановив приложение при этом.

2 голосов
/ 10 февраля 2010

Опираясь на комментарий атайлора к вопросу:

Возможно, вы захотите вложить свой цикл. Что-то вроде

for i in range(1,n):
    for each in range n:
        fp.write('something')
fp.close()

Таким образом, единственное, что помещается в память, это строка "something", а не "something" * n.

1 голос
/ 10 февраля 2010

Если вы записываете большой файл, для которого может произойти сбой записи, лучше записывать файл на диск самостоятельно через регулярные интервалы, используя fp.flush(). Таким образом, файл будет находиться в выбранном вами месте, к которому вы можете легко добраться, а не во власти ОС:

fp = open('output.txt', 'wb')
counter = 0
for line in many_lines:
    file.write(line)
    counter += 1
    if counter > 999:
        fp.flush()
fp.close()

Это будет сбрасывать файл на диск каждые 1000 строк.

0 голосов
/ 10 февраля 2010

Запись файла никогда не должна давать ошибку памяти; по всей вероятности, у вас есть ошибка в другом месте.

Если у вас есть цикл и ошибка памяти, я бы посмотрел, если вы «просочились» ссылки на объекты.
Что-то вроде:

def do_something(a, b = []):
    b.append(a)
    return b

fp = open('output.txt', 'wb') 

for i in range(1, n): 
    something = do_something(i)
    fp.write(something)

fp.close()

Сейчас я выбираю только пример, но в вашем реальном случае найти утечку эталона может быть гораздо сложнее; однако в этом случае будет просто утечка памяти внутри do_something из-за способа, которым Python обрабатывает параметры функций по умолчанию.

0 голосов
/ 10 февраля 2010

Если вы пишете построчно, это не должно быть проблемой. Вы должны показать код того, что вы делаете перед записью. Для начала вы можете попробовать удалить объекты там, где это не нужно, используйте fp.flush() и т.д ..

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