Как скачать файлы с помощью Python?

Всем привет. Я новичок в Python и использую Python 2.5 в CentOS.

Мне нужно скачать файлы, как это делает WGET.

Я провел некоторый поиск, и есть несколько решений, очевидным способом является следующее:

import urllib2
mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
output = open('test.mp3','wb')
output.write(mp3file.read())
output.close()

Это прекрасно работает. Но я хочу знать, если файл mp3 ОЧЕНЬ большой, например, 1 ГБ, 2 ГБ или даже больше. Может ли этот фрагмент кода работать? Есть ли лучшие способы загрузки больших файлов в Python, возможно, с индикатором выполнения, например WGET.

Большое спасибо!


person DocWiki    schedule 09.12.2010    source источник
comment
Я предполагаю, что ваш вопрос касается итеративного чтения и записи фрагмента за раз, а не чтения всего файла в память сразу только для последующей записи всего на диск.   -  person chrisaycock    schedule 10.12.2010
comment
возможный дубликат Поток больших двоичных файлов с urllib2 в файл   -  person Katriel    schedule 10.12.2010


Ответы (4)


Есть более простой способ:

import urllib
urllib.urlretrieve("http://www.example.com/songs/mp3.mp3", "/home/download/mp3.mp3")
person Paul Schreiber    schedule 09.12.2010

Для действительно больших файлов ваш код будет использовать много памяти, так как вы загружаете весь файл в память сразу. Возможно, лучше читать и записывать данные порциями:

from __future__ import with_statement
import urllib2
mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
with open('test.mp3','wb') as output:
    while True:
        buf = mp3file.read(65536)
        if not buf:
            break
        output.write(buf)
person Sven Marnach    schedule 09.12.2010

Почему бы тогда просто не позвонить wget?

import os
os.system ("wget http://www.example.com/songs/mp3.mp3")
person chrisaycock    schedule 09.12.2010
comment
Спасибо за это. Безопасен ли этот метод? Похоже, довольно высоки шансы привести к краху системы... потому что мало кто использует этот метод, насколько я знаю. - person DocWiki; 10.12.2010
comment
И, похоже, нет способа узнать, успешен ли метод wget или нет. Пожалуйста, проверьте эту страницу: http://linux.byexamples.com/archives/366/python-how-to-run-a-command-line-within-python/ - person DocWiki; 10.12.2010
comment
@DocWiki Я предпочитаю себя curl wget. Однако системные вызовы — это всегда сложное предложение. Я сам проголосовал за urlretrieve ответ @Paul. - person chrisaycock; 10.12.2010
comment
У этого также есть обратная сторона (в зависимости от того, что вы делаете), что для этого требуется wget, т.е. он не будет работать в Windows, в отличие от чистого решения Python. - person Thomas K; 10.12.2010

ваш текущий код будет считывать весь поток в память перед записью на диск. Поэтому в случаях, когда файл больше доступной памяти, вы столкнетесь с проблемами.

чтобы решить эту проблему, вы можете читать фрагменты за раз и записывать их в файл.


(скопировано из Поток больших двоичных файлов с urllib2 в файл)

req = urllib2.urlopen(url)
CHUNK = 16 * 1024
with open(file, 'wb') as fp:
  while True:
    chunk = req.read(CHUNK)
    if not chunk: break
    fp.write(chunk)

«Поэкспериментируйте немного с различными размерами CHUNK, чтобы найти «золотую середину» для ваших требований».

person Corey Goldberg    schedule 09.12.2010