Я загружаю потенциально большие файлы на веб-сервер. В настоящее время я делаю это:
import urllib2
f = open('somelargefile.zip','rb')
request = urllib2.Request(url,f.read())
request.add_header("Content-Type", "application/zip")
response = urllib2.urlopen(request)
Однако это читает содержание всего файла в память прежде, чем отправить его. Как у меня может быть он, передают файл потоком к серверу?
Просматривая цепочку рассылки, на которую ссылается systempuntoout, я нашел ключ к решению.
Модуль mmap
позволяет открывать файл, который действует как строка. Части файла загружаются в память по запросу.
Вот код, который я сейчас использую:
import urllib2
import mmap
# Open the file as a memory mapped string. Looks like a string, but
# actually accesses the file behind the scenes.
f = open('somelargefile.zip','rb')
mmapped_file_as_string = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
# Do the request
request = urllib2.Request(url, mmapped_file_as_string)
request.add_header("Content-Type", "application/zip")
response = urllib2.urlopen(request)
#close everything
mmapped_file_as_string.close()
f.close()
Попробуйте pycurl. У меня ничего нет, установка примет большой файл, который не в POST multipart / form-data, но вот простой пример, который читает файл по мере необходимости.
import os
import pycurl
class FileReader:
def __init__(self, fp):
self.fp = fp
def read_callback(self, size):
return self.fp.read(size)
c = pycurl.Curl()
c.setopt(pycurl.URL, url)
c.setopt(pycurl.UPLOAD, 1)
c.setopt(pycurl.READFUNCTION, FileReader(open(filename, 'rb')).read_callback)
filesize = os.path.getsize(filename)
c.setopt(pycurl.INFILESIZE, filesize)
c.perform()
c.close()
Вы пробовали использовать Mechanize ?
from mechanize import Browser
br = Browser()
br.open(url)
br.form.add_file(open('largefile.zip'), 'application/zip', 'largefile.zip')
br.submit()
или, если вы не хотите использовать multipart / form-data, проверьте эту старую публикацию.
Предлагаются два варианта:
1. Use mmap, Memory Mapped file object
2. Patch httplib.HTTPConnection.send