Python Requests中multipart/form-data支持生成器的技术问询
在multipart/form-data请求中使用生成器的可行性问题
我曾将生成器作为参数传入Content-Type: application/json请求的data参数中,运行正常。现在需要在multipart/form-data类型的请求中使用生成器,但发现该类型似乎不支持生成器。
已尝试的方案及报错情况
- 使用
files={'content': my_generator_func()},报错:"a bytes-like object is required, not 'generator'",说明该参数仅接受文件描述符,不支持生成器。 - 在
data参数中传入生成器,同时通过files={'encoding': (None, 'base64')}触发multipart请求,报错:"Streamed bodies and files are mutually exclusive"。 - 手动设置
Content-Type: multipart/form-data请求头,无论是否设置都存在问题:不设置时提示缺少该头,设置时出现上述"流主体与文件互斥"的错误。 - 使用MultipartEncoder工具,它接受文件描述符,但不支持直接传入生成器。
代码示例
基础尝试代码
def my_generator(): '迭代时返回"value_fragment1;value_fragment2;"' yield 'value_fragment1;' yield 'value_fragment2;' response=requests.post(url, # 试过添加/移除这个请求头... headers={'Content-Type': 'multipart/form-data'}, data={'field1': (None, 'value1'), 'field2': (None, 'value2') }, # 按照相关帖子的方式设置multipart的data参数... files={'field3', my_generator()} ) # 这段代码触发了"生成器不符合预期"的错误
使用StreamingIterator的尝试代码
from requests_toolbelt.streaming_iterator import StreamingIterator # 示例中仅用于获取内容长度;实际场景会自行计算长度 content='' for fragment in my_generator(): content+=fragment streamer=StreamingIterator(len(content), my_generator()) response=requests.post(url, # 试过添加/移除这个请求头... headers={'Content-Type': 'multipart/form-data'}, data={'field1': (None, 'value1'), 'field2': (None, 'value2') }, # 按照相关帖子的方式设置multipart的data参数... files={'field3', streamer} ) # 服务端无法识别提交的字段,但使用curl的`--form field1=value1 --form field2=value2`命令能正常提交
后续尝试的问题
尝试将生成器包装成类接入MultipartEncoder时,遇到了seek操作不支持的错误:
File "/usr/lib/python3/dist-packages/requests_toolbelt/multipart/encoder.py", line 573, in len return total_len(self.fd) - self.fd.tell() ^^^^^^^^^^^^^^ io.UnsupportedOperation: seek
还尝试将StreamingIterator传入MultipartEncoder,请求直接陷入挂起状态。
疑问
是否可以在multipart/form-data请求中使用生成器?如果必须的话,我会将流写入文件后传入文件描述符,但既然application/json支持生成器,multipart/form-data应该也提供相应的实现方式。看起来requests[toolbelt]的开发者遗漏了对multipart/form-data请求支持生成器的实现。
内容的提问来源于stack exchange,提问作者Steve B.
相关产品推荐
相关产品推荐

