Утекает ли память os.walk?

Когда я запускаю этот скрипт Python в Windows, процесс растет без видимого конца:

import os

for i in xrange(1000000):
    for root, dirs, files in os.walk(r"c:\windows"):
        pass

Я что-то неправильно понимаю? (Я использую Python 2.7.3.)


person user1687699    schedule 21.09.2012    source источник
comment
Хорошо. C:\windows - это большой график для ходьбы, верно? Довольно глубоко. Очень глубоко. Как рост процесса соотносится с утечкой памяти?   -  person CppLearner    schedule 21.09.2012
comment
Процесс увеличивается примерно на 7 МБ каждый раз во внешнем цикле. Я могу понять использование большого количества памяти для одного обхода, но не следует ли использовать ее повторно после этого?   -  person user1687699    schedule 21.09.2012
comment
@user1687669 user1687669 Вы должны загрузить что-то в память. Возможно, сборщик мусора не очистил его сразу, потому что в GC есть понятие счетчика ссылок. Если счетчик ссылок не равен нулю, он будет оставаться в памяти в течение некоторого периода времени. Это возможно. Одна из возможных проблем с памятью, вероятно, связана с метаданными файловой системы. К каждому файлу/папке прикреплены метаданные, такие как режим, пользователь, дата и т. д. Я действительно рассмотрю это, потому что мой проект действительно работает с файловой системой, поэтому здорово, что вы действительно подняли этот вопрос.   -  person CppLearner    schedule 21.09.2012
comment
Запуская тот же код, ту же версию Python под 64-битной Windows 7, процесс не превышает 7 МБ, возвращаясь примерно к 4 МБ каждый раз, когда заканчивается внешний цикл. Это справедливо как для 32-битной, так и для 64-битной версии Python 2.7.3. Это именно тот сценарий, который вы используете?   -  person Matthew Trevor    schedule 21.09.2012
comment
Да, это точный сценарий. Я пробовал это на двух разных машинах под управлением 32-битной Windows 7. Я измеряю использование в столбце «Память — частный рабочий набор» диспетчера задач. Я получаю те же результаты, что и приватные байты в Process Explorer.   -  person user1687699    schedule 21.09.2012
comment
Я только что воспроизвел его на третьей машине с 64-битной Windows 7 и 32-битным Python.   -  person user1687699    schedule 21.09.2012
comment
Я позволил ему работать, пока не закончилась память: C:\Users\Eric\Documents›test.py Traceback (последний последний вызов): Файл C:\Users\Eric\Documents\test.py, строка 4, в ‹ module› для root, каталогов, файлов в os.walk(rc:\windows): Файл S:\Python27\lib\os.py, строка 294, in walk for x in walk(new_path, topdown, onerror, followlinks): Файл S:\Python27\lib\os.py, строка 294, в прогулке для x в прогулке (новый_путь, сверху вниз, при ошибке, следующие ссылки): Файл S:\Python27\lib\os.py, строка 287, в прогулке недир. добавить (имя) MemoryError   -  person user1687699    schedule 21.09.2012
comment
Я начинаю понимать, что вы имеете в виду, @user1687699 Мое предыдущее предположение о данных может быть неверным. Я написал несколько тестовых сценариев. Позвольте мне сделать это в Windows.   -  person CppLearner    schedule 22.09.2012
comment
...Зачем вы миллион раз обходите дерево ОС?   -  person Makoto    schedule 01.10.2012


Ответы (1)


Это связано с утечкой памяти в os.path.isdir; см. Огромная утечка памяти при повторных вызовах os.path.isdir? Вы можете проверить это самостоятельно, используя строку пути в кодировке Unicode — утечки быть не должно.

os.path.isdir используется в реализации os.walk:

    islink, join, isdir = path.islink, path.join, path.isdir
    try:
        names = listdir(top)
    except error, err:
        if onerror is not None:
            onerror(err)
        return

    dirs, nondirs = [], []
    for name in names:
        if isdir(join(top, name)):
            dirs.append(name)
        else:
            nondirs.append(name)
person AAlon    schedule 30.09.2012