Python 如何使用请求解决此AttributeError';s多部分表单数据发布?

Python 如何使用请求解决此AttributeError';s多部分表单数据发布?,python,python-2.7,python-requests,Python,Python 2.7,Python Requests,我正在尝试将文件发布到我的graphqlendpoint@scaphold.io。我通常编写Javascript,但我必须将此特定操作转换为Python 使用curl执行此操作的命令如下(): 其中variables中的blobFieldName属性与保存要上载的文件的表单字段名匹配 使用请求,我已经做到了这一点: import requests from requests_toolbelt import MultipartEncoder url = 'https://us-west-2.ap

我正在尝试将文件发布到我的
graphql
endpoint@scaphold.io。我通常编写
Javascript
,但我必须将此特定操作转换为
Python

使用
curl
执行此操作的命令如下():

其中
variables
中的
blobFieldName
属性与保存要上载的文件的
表单
字段名匹配

使用
请求
,我已经做到了这一点:

import requests
from requests_toolbelt import MultipartEncoder

url = 'https://us-west-2.api.scaphold.io/graphql/scaphold-graphql'
multipart_data = MultipartEncoder(
    fields={
        "query":"mutation CreateFile($input: CreateFileInput!) { createFile(input: $input) { changedFile { id name blobMimeType blobUrl user { id username } } } }",
        "variables": { "input": { "name": "Profile Picture", "userId": "VXNlcjoxMA==", "blobFieldName": "myBlobField" } },
        "type":'application/json',
        "myBlobField": ('example.jpg', open('example.jpg', 'rb'), 'image/jpeg' )
        }      
)
req_headers = {'Content-Type':multipart_data.content_type, 'Authorization':'Bearer myreallylongkey'}

r = requests.post(url, data=multipart_data, headers=req_headers)
不幸的是,这遇到了
属性错误

Traceback (most recent call last):
  File "test-gql.py", line 38, in <module>
    "myBlobField": ('example.jpg', open('example.jpg', 'rb'), 'image/jpeg' )
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 119, in __init__
    self._prepare_parts()
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 240, in _prepare_parts
    self.parts = [Part.from_field(f, enc) for f in self._iter_fields()]
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 488, in from_field
    body = coerce_data(field.data, encoding)
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 466, in coerce_data
    return CustomBytesIO(data, encoding)
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 529, in __init__
    buffer = encode_with(buffer, encoding)
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 410, in encode_with
    return string.encode(encoding)
AttributeError: 'dict' object has no attribute 'encode'
回溯(最近一次呼叫最后一次):
文件“test gql.py”,第38行,在
“myBlobField”:('example.jpg',open('example.jpg','rb'),'image/jpeg')
文件“/home/bmp/code/wayhome/python phash/requests\u toolbelt/multipart/encoder.py”,第119行,在__
自行准备零件()
文件“/home/bmp/code/wayhome/python phash/requests\u toolbelt/multipart/encoder.py”,第240行,在“准备”部分中
self.parts=[self中f的Part.from_字段(f,enc).\u iter_字段()]
文件“/home/bmp/code/wayhome/python phash/requests\u toolbelt/multipart/encoder.py”,第488行,在from\u字段中
body=强制_数据(field.data,编码)
强制数据中的文件“/home/bmp/code/wayhome/python phash/requests\u toolbelt/multipart/encoder.py”,第466行
返回CustomBytesIO(数据、编码)
文件“/home/bmp/code/wayhome/python phash/requests\u toolbelt/multipart/encoder.py”,第529行,在__
缓冲区=使用(缓冲区,编码)编码
文件“/home/bmp/code/wayhome/python phash/requests_toolbelt/multipart/encoder.py”,第410行,在encode_中使用
返回字符串.encode(编码)
AttributeError:“dict”对象没有属性“encode”
恐怕我没有足够的能力去探究这个错误,但我已经排除了几个嫌疑犯:

  • 将一个简单的
    query
    curl
    翻译成
    Python
    很好,所以我知道这不是权限,等等
  • 使用不同的
    纯/文本
    风格的文件失败,但出现相同错误
  • 对于
    字段
    (),使用元组的元组而不是
    dict
    ,没有效果

从您的示例中可以看出,您似乎将“变量”作为字典传递,但它应该是字符串。改变

        "variables": { "input": { "name": "Profile Picture", "userId": "VXNlcjoxMA==", "blobFieldName": "myBlobField" } },

请注意使用单引号使其成为字符串
编辑::从MultipartEncoder的代码中,MultipartEncoder尝试对值运行.encode(…)方法。encode(…)带有字符串。因为键“variables”的值的数据类型是dict,.encode(…)似乎在这方面失败。

从您的示例来看,您似乎将“variables”作为字典传递,但它应该是字符串。改变

        "variables": { "input": { "name": "Profile Picture", "userId": "VXNlcjoxMA==", "blobFieldName": "myBlobField" } },

请注意使用单引号使其成为字符串
编辑::从MultipartEncoder的代码中,MultipartEncoder尝试对值运行.encode(…)方法。encode(…)带有字符串。因为键“variables”的值的数据类型是dict,.encode(…)似乎失败了。

curl转换器:看看你的最后一个链接-它们使用tuple与
文件=
,而不是
数据=
@furas谢谢,这些转换器很棒(特别是第一个)。如果有人尝试,请注意:第二个转换器只支持Python3,而第一个转换器似乎错误地截断了带有
=
字符的任何字符串。否则,其代码看起来是正确的。回复:
文件
数据
相比,我相信当使用
多端口编码
时,参数会变为
数据
。我可以说,
data
在实现公认答案中的解决方案时起到了作用,至少。curl converters:请查看您的最后一个链接-它们使用tuple with
files=
,而不是
data=
@furas谢谢,这些转换器非常棒(特别是第一个)。如果有人尝试,请注意:第二个转换器只支持Python3,而第一个转换器似乎错误地截断了带有
=
字符的任何字符串。否则,其代码看起来是正确的。回复:
文件
数据
相比,我相信当使用
多端口编码
时,参数会变为
数据
。我可以说,至少在公认的答案中实施解决方案时,
数据
起了作用。
        "variables": '{ "input": { "name": "Profile Picture", "userId": "VXNlcjoxMA==", "blobFieldName": "myBlobField" } }',