Python: HTTP Publicar un archivo grande con transmisión

Estoy cargando archivos potencialmente grandes a un servidor web. Actualmente estoy haciendo esto:

import urllib2 f = open('somelargefile.zip','rb') request = urllib2.Request(url,f.read()) request.add_header("Content-Type", "application/zip") response = urllib2.urlopen(request) 

Sin embargo, esto lee todo el contenido del archivo en la memoria antes de publicarlo. ¿Cómo puedo hacer que transmita el archivo al servidor?

Al leer el hilo de la lista de correo vinculado a systempuntoout, encontré una pista hacia la solución.

El módulo mmap permite abrir un archivo que actúa como una cadena. Las partes del archivo se cargan en la memoria a pedido.

Aquí está el código que estoy usando ahora:

 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() 

¿Has probado con mecanizar ?

 from mechanize import Browser br = Browser() br.open(url) br.form.add_file(open('largefile.zip'), 'application/zip', 'largefile.zip') br.submit() 

o, si no quieres usar multipart / form-data, revisa esta publicación anterior.

Sugiere dos opciones:

  1. Use mmap, Memory Mapped file object 2. Patch httplib.HTTPConnection.send 

La documentación no indica que puede hacer esto, pero el código en urllib2 (y httplib) acepta cualquier objeto con un método read () como datos. Así que usar un archivo abierto parece hacer el truco.

Tendrá que configurar el encabezado Content-Length usted mismo. Si no está configurado, urllib2 llamará a len () en los datos, qué objetos de archivo no son compatibles.

 import os.path import urllib2 data = open(filename, 'r') headers = { 'Content-Length' : os.path.getsize(filename) } response = urllib2.urlopen(url, data, headers) 

Este es el código relevante que maneja los datos que usted suministra. Es de la clase httplib.py en httplib.py en Python 2.7:

 def send(self, data): """Send `data' to the server.""" if self.sock is None: if self.auto_open: self.connect() else: raise NotConnected() if self.debuglevel > 0: print "send:", repr(data) blocksize = 8192 if hasattr(data,'read') and not isinstance(data, array): if self.debuglevel > 0: print "sendIng a read()able" datablock = data.read(blocksize) while datablock: self.sock.sendall(datablock) datablock = data.read(blocksize) else: self.sock.sendall(data) 

Pruebe pycurl. No tengo nada configurado que acepte un archivo grande que no esté en un POST multipart / form-data, pero aquí hay un ejemplo simple que lee el archivo según sea necesario.

 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() 

Usando la biblioteca de requests puedes hacer

 with open('massive-body', 'rb') as f: requests.post('http://some.url/streamed', data=f) 

como se menciona aquí en sus documentos

No puedo (aún) comentar sobre la respuesta de Brian https://stackoverflow.com/a/30810626/9921853

urllib2.urlopen (url, data, headers) no toma los encabezados como parámetro, por lo que no funcionará

A continuación se muestra el ejemplo de trabajo para Python 2 / Python 3:

 try: from urllib2 import urlopen, Request except: from urllib.request import urlopen, Request headers = { 'Content-length': str(os.path.getsize(filepath)) } with open(filepath, 'rb') as f: req = Request(url, data=f, headers=headers) result = urlopen(req).read().decode() 

El módulo de solicitudes es excelente, pero a veces no se pueden instalar módulos adicionales …