Python: непредсказуемая ошибка памяти при загрузке больших файлов - PullRequest
5 голосов
/ 31 марта 2011

Я написал скрипт на Python, который я использую для загрузки большого количества видеофайлов (по 50–400 МБ каждый) с HTTP-сервера.До сих пор он хорошо работал в длинных списках загрузок, но по некоторым причинам у него редко бывает ошибка памяти.

На машине имеется около 1 ГБ свободной оперативной памяти, но я не думаю, что она когда-либо исчерпала объем ОЗУ при выполнении этого сценария.

Я наблюдал за использованием памяти в диспетчере задач и perfmon, и он всегда ведет себя так же, как я видел: медленно увеличивается во время загрузки, затем возвращается к нормальному уровню после завершения загрузки (естьнет мелких утечек, которые ползут или что-то в этом роде.

Способ загрузки заключается в том, что он создает файл, который остается равным 0 КБ до завершения загрузки (или до сбоя программы), затем записываетвесь файл сразу и закрывает его.

for i in range(len(urls)):
    if os.path.exists(folderName + '/' + filenames[i] + '.mov'):
        print 'File exists, continuing.'
        continue

    # Request the download page
    req = urllib2.Request(urls[i], headers = headers)

    sock = urllib2.urlopen(req)
    responseHeaders = sock.headers
    body = sock.read()
    sock.close()

    # Search the page for the download URL
    tmp = body.find('/getfile/')
    downloadSuffix = body[tmp:body.find('"', tmp)]
    downloadUrl = domain + downloadSuffix

    req = urllib2.Request(downloadUrl, headers = headers)

    print '%s Downloading %s, file %i of %i'
        % (time.ctime(), filenames[i], i+1, len(urls))

    f = urllib2.urlopen(req)

    # Open our local file for writing, 'b' for binary file mode
    video_file = open(foldername + '/' + filenames[i] + '.mov', 'wb')

    # Write the downloaded data to the local file
    video_file.write(f.read()) ##### MemoryError: out of memory #####
    video_file.close()

    print '%s Download complete!' % (time.ctime())

    # Free up memory, in hopes of preventing memory errors
    del f
    del video_file

Вот трассировка стека:

  File "downloadVideos.py", line 159, in <module>
    main()
  File "downloadVideos.py", line 136, in main
    video_file.write(f.read())
  File "c:\python27\lib\socket.py", line 358, in read
    buf.write(data)
MemoryError: out of memory

1 Ответ

9 голосов
/ 31 марта 2011

Ваша проблема здесь: f.read().Эта строка пытается загрузить весь файл в память.Вместо этого читайте кусками (chunk = f.read(4096)) и сохраняйте фрагменты во временном файле.

...