Biblioteca estándar de Python para POST multiparte / datos codificados de datos de formulario

Me gustaría publicar datos codificados multiparte / datos de formulario. He encontrado un módulo externo que lo hace: http://atlee.ca/software/poster/index.html, sin embargo, preferiría evitar esta dependencia. ¿Hay alguna manera de hacer esto usando las bibliotecas estándar?

Gracias

La biblioteca estándar no soporta eso actualmente . Sin embargo, hay una receta de libro de cocina que incluye un fragmento de código bastante corto que quizás desee copiar, junto con largas discusiones sobre alternativas.

Es un tema antiguo, pero sigue siendo popular, así que aquí está mi contribución utilizando solo módulos estándar.

La idea es la misma que aquí, pero admite Python 2.xy Python 3.x. También tiene un generador de cuerpo para evitar el uso innecesario de la memoria.

import codecs import mimetypes import sys import uuid try: import io except ImportError: pass # io is requiered in python3 but not available in python2 class MultipartFormdataEncoder(object): def __init__(self): self.boundary = uuid.uuid4().hex self.content_type = 'multipart/form-data; boundary={}'.format(self.boundary) @classmethod def u(cls, s): if sys.hexversion < 0x03000000 and isinstance(s, str): s = s.decode('utf-8') if sys.hexversion >= 0x03000000 and isinstance(s, bytes): s = s.decode('utf-8') return s def iter(self, fields, files): """ fields is a sequence of (name, value) elements for regular form fields. files is a sequence of (name, filename, file-type) elements for data to be uploaded as files Yield body's chunk as bytes """ encoder = codecs.getencoder('utf-8') for (key, value) in fields: key = self.u(key) yield encoder('--{}\r\n'.format(self.boundary)) yield encoder(self.u('Content-Disposition: form-data; name="{}"\r\n').format(key)) yield encoder('\r\n') if isinstance(value, int) or isinstance(value, float): value = str(value) yield encoder(self.u(value)) yield encoder('\r\n') for (key, filename, fd) in files: key = self.u(key) filename = self.u(filename) yield encoder('--{}\r\n'.format(self.boundary)) yield encoder(self.u('Content-Disposition: form-data; name="{}"; filename="{}"\r\n').format(key, filename)) yield encoder('Content-Type: {}\r\n'.format(mimetypes.guess_type(filename)[0] or 'application/octet-stream')) yield encoder('\r\n') with fd: buff = fd.read() yield (buff, len(buff)) yield encoder('\r\n') yield encoder('--{}--\r\n'.format(self.boundary)) def encode(self, fields, files): body = io.BytesIO() for chunk, chunk_len in self.iter(fields, files): body.write(chunk) return self.content_type, body.getvalue() 

Manifestación

 # some utf8 key/value pairs fields = [('প্রায়', 42), ('bar', b'23'), ('foo', 'ން:')] files = [('myfile', 'image.jpg', open('image.jpg', 'rb'))] # iterate and write chunk in a socket content_type, body = MultipartFormdataEncoder().encode(fields, files) 

No se puede hacer esto rápidamente con el estándar. Howevewr, vea la clase MultiPartForm en este PyMOTW. Probablemente puedas usarlo o modificarlo para lograr lo que necesites:

  • PyMOTW: urllib2 – Biblioteca para abrir URL.