使用Python Requests PUT请求时遇memoryview类型错误求助
问题:使用Interact API更新页面时触发memoryview类型错误
问题背景
我们用Interact作为内网供应商,尝试通过其API更新页面审核日期。获取token鉴权环节正常,也能通过API读取数据,但执行PUT请求更新页面时,出现依赖库类型错误。
错误信息
Error with updating page data... memoryview: a bytes-like object is required, not 'str' Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 998, in send self.sock.sendall(data) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/ssl.py", line 1233, in sendall with memoryview(data) as view, view.cast("B") as byte_view: TypeError: memoryview: a bytes-like object is required, not 'str' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/Users/xxxxxxxxxx/Desktop/xxxxxx/Projects/Intranet/Development/updateReviewDate.py", line 133, in updatePages response = requests.put(strURL, data={jsonPage}, headers=dictHeader) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/requests/api.py", line 130, in put return request("put", url, data=data, **kwargs) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/requests/api.py", line 59, in request return session.request(method=method, url=url, **kwargs) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/requests/sessions.py", line 587, in request resp = self.send(prep, **send_kwargs) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/requests/sessions.py", line 701, in send r = adapter.send(request, **kwargs) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/requests/adapters.py", line 489, in send resp = conn.urlopen( File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/urllib3/connectionpool.py", line 703, in urlopen httplib_response = self._make_request( File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/urllib3/connectionpool.py", line 398, in _make_request conn.request(method, url, **httplib_request_kw) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/urllib3/connection.py", line 239, in request super(HTTPConnection, self).request(method, url, body=body, headers=headers) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 1282, in request self._send_request(method, url, body, headers, encode_chunked) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 1328, in _send_request self.endheaders(body, encode_chunked=encode_chunked) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 1277, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 1076, in _send_output self.send(chunk) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 1002, in send self.sock.sendall(d) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/ssl.py", line 1233, in sendall with memoryview(data) as view, view.cast("B") as byte_view: TypeError: memoryview: a bytes-like object is required, not 'str'
相关代码
def updatePages(dictPages): for pageId in dictPages: dictPage = dictPages[pageId] jsonPage = json.dumps(dictPage, indent = 4) print(jsonPage) strURL = rootURL + "api/page/" + pageId + "/composer" dictHeader = {"Content-Type": "application/x-www-form-urlencoded; charset=utf-8", "accept": "application/json", "X-Tenant":tenantGuid, "Authorization": "Bearer " + accessToken} try: response = requests.put(strURL, data={jsonPage}, headers=dictHeader) print(response.json()) except Exception as e: print("Error with updating page data...") print(e) print(traceback.format_exc()) break
待发送的JSON数据(已通过语法校验)
{ "Transition": { "State": "published", "Message": "Updating the review date" }, "Page": { "ContentType": "html", "TopSectionIds": 4070, "AuthorId": 449, "Title": "How to refer a candidate to an open position", "Summary": "Help Recruit a Talented Individual and Collect a Bonus.", "Features": { "DefaultToFullWidth": true, "AllowComments": true, "IsKeyPage": false, "Recommends": { "Show": true, "MaxContentAge": 7 } }, "PubStartDate": "2022-09-20T20:31:12.3+00:00", "PubEndDate": "2025-09-20T09:00:00.0000000Z", "ReviewDate": "2023-03-20T09:00:00.0000000Z", "TagIds": [], "Keywords": [] } }
解决方案
问题出在两个地方,不需要手动转二进制数据:
Content-Type设置错误:你当前设置的是
application/x-www-form-urlencoded,但API接收的是JSON格式,应该把Content-Type改为application/json。请求数据传递错误:你把序列化后的JSON字符串放到了集合
{jsonPage}里传给data参数,这会让requests把它当成表单数据处理,导致内部类型转换出错。更简单的做法是直接用requests的json参数,传入原始字典dictPage,requests会自动帮你完成JSON序列化,并正确设置Content-Type(即使你没手动设置)。
修改后的代码片段:
def updatePages(dictPages): for pageId in dictPages: dictPage = dictPages[pageId] print(json.dumps(dictPage, indent=4)) strURL = rootURL + "api/page/" + pageId + "/composer" # 简化headers,Content-Type可以省略,requests会自动添加 dictHeader = {"accept": "application/json", "X-Tenant":tenantGuid, "Authorization": "Bearer " + accessToken} try: # 直接用json参数传字典 response = requests.put(strURL, json=dictPage, headers=dictHeader) print(response.json()) except Exception as e: print("Error with updating page data...") print(e) print(traceback.format_exc()) break
如果还是想手动序列化JSON字符串,那应该直接传字符串给data参数,同时设置正确的Content-Type:
response = requests.put(strURL, data=jsonPage, headers={"Content-Type": "application/json", **dictHeader})
内容的提问来源于stack exchange,提问作者PruitIgoe
相关产品推荐
相关产品推荐

