Problemas con multipart_encode (biblioteca de carteles)

Estoy intentando cargar un archivo utilizando multipart_encode para realizar el proceso MIME . Sin embargo, encontré el siguiente error AttributeError: multipart_yielder instance has no attribute '__len__' . A continuación se muestra mi enfoque, realmente aprecio si alguien me puede dar algunas sugerencias.

 url = "https://pi-user-files.s3-external-1.amazonaws.com/" post_data = {} #data is a dict post_data['AWSAccessKeyId']=(data['ticket']['AWSAccessKeyId']) post_data['success_action_redirect']=(data['ticket']['success_action_redirect']) post_data['acl']=(data['ticket']['acl']) post_data['key']=(data['ticket']['key']) post_data['signature']=(data['ticket']['signature']) post_data['policy']=(data['ticket']['policy']) post_data['Content-Type']=(data['ticket']['Content-Type']) #I would like to upload a text file "new 2" post_data['file']=open("new 2.txt", "rb") datagen, headers = multipart_encode(post_data) request2 = urllib2.Request(url, datagen, headers) result = urllib2.urlopen(request2) 

El problema es que en httplib.py, el generador no se detecta como tal y, en cambio, se trata como una cadena que contiene los datos completos que se enviarán (y, por lo tanto, intenta encontrar su longitud):

 if hasattr(data,'read') and not isinstance(data, array): # generator if self.debuglevel > 0: print "sendIng a read()able" .... 

Una solución es hacer que el generador actúe como un lector () capaz de:

 class GeneratorToReadable(): def __init__(self, datagen): self.generator = datagen self._end = False self.data = '' def read(self, n_bytes): while not self._end and len(self.data) < n_bytes: try: next_chunk = self.generator.next() if next_chunk: self.data += next_chunk else: self._end = True except StopIteration: self._end = True result = self.data[0:n_bytes] self.data = self.data[n_bytes:] return result 

y usar como tal:

 datagen, headers = multipart_encode(post_data) readable = GeneratorToReadable(datagen) req = urllib2.Request(url, readable, headers) result = urllib2.urlopen(req) 

Si desea enviar un archivo, debe envolver otros parámetros con un objeto MultipartParam , código de ejemplo para crear una solicitud de envío de archivos:

 from poster.encode import multipart_encode, MultipartParam import urllib2 def postFileRequest(url, paramName, fileObj, additionalHeaders={}, additionalParams={}): items = [] #wrap post parameters for name, value in additionalParams.items(): items.append(MultipartParam(name, value)) #add file items.append(MultipartParam.from_file(paramName, fileObj)) datagen, headers = multipart_encode(items) #add headers for item, value in additionalHeaders.iteritems(): headers[item] = value return urllib2.Request(url, datagen, headers) 

También creo que deberías ejecutar register_openers() una vez al principio. Algunos detalles que puedes encontrar en docs.