用于POST多部分/表单数据编码数据的Python标准库

hoj*_*oju 20 python post encoding multipart urllib

我想POST多部分/表格数据编码数据.我找到了一个外部模块来执行它:http://atlee.ca/software/poster/index.html 但是我宁愿避免这种依赖.有没有办法使用标准库?

谢谢

Mar*_*wis 17

标准库目前不支持.有一个食谱配方,包括你可能想要复制的相当短的代码,以及对替代品的长时间讨论.


tic*_*pix 13

这是一个老线程,但仍然是一个受欢迎的线程,所以这是我的贡献只使用标准模块.

这个想法与此相同,但支持Python 2.x和Python 3.x. 它还有一个体生成器,以避免不必要的内存使用.

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()
Run Code Online (Sandbox Code Playgroud)

演示

# 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)
Run Code Online (Sandbox Code Playgroud)


ars*_*ars 6

您无法快速使用stdlib执行此操作.Howevewr,看看MultiPartForm这个PyMOTW中的类.你可以使用或修改它来完成你需要的任何东西: