欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TypeError:POST data should be bytes, an iterable of bytes, or a file object. It cannot be of str

程序员文章站 2022-03-08 16:43:10
...

Python2转Python3,调用API在线服务遇到的问题解决(json数据)

Python2代码示例:

import json
import traceback
import urllib
import urllib2

# json格式数据
formdata = {
    "CRIM":0.01887747, 
    "ZN":-0.11363636, 
    "INDUS":0.25525005, 
    "CHAS":-0.06916996
}
header = {"Content-Type": "application/json; charset=utf-8"}
url = "https://aistudio.baidu.com/serving/online/xxx?apiKey=a280cf48-6d0c-4baf-bd39xxxxxxcxxxxx"
data = json.dumps(formdata)
try:
    request = urllib2.Request(url, data, header)
    response = urllib2.urlopen(request)
    response_str = response.read()
    response.close()
    print(response_str)
except urllib2.HTTPError as e:
    print("The server couldn't fulfill the request")
    print(e.code)
    print(e.read())
except urllib2.URLError as e:
    print("Failed to reach the server")
    print(e.reason)
except:
    traceback.print_exc()

修改到Python3的代码

import json
import traceback
import urllib
# 1.首先去掉urllib2, python3统一使用urllib
# import urllib2

# json数据
formdata = {
    "CRIM":0.01887747, 
    "ZN":-0.11363636, 
    "INDUS":0.25525005, 
    "CHAS":-0.06916996
}
header = {"Content-Type": "application/json; charset=utf-8"}
url = "https://aistudio.baidu.com/serving/online/xxx?apiKey=a280cf48-6d0c-4baf-bd39xxxxxxcxxxxx"
data = json.dumps(formdata)

# 2.urllib2到urllib转换的语句修改
try:
    request = urllib.request.Request(url, data, header)
    # 输出字符串
    response = urllib.request.urlopen(request)
    response_str = response.read()
    response.close()
    print(response_str)
except urllib.error.HTTPError as e:
    print("The server couldn't fulfill the request")
    print(e.code)
    print(e.read())
except urllib.error.URLError as e:
    print("Failed to reach the server")
    print(e.reason)
except:
    traceback.print_exc()

但,运行之后会报如下错误:

TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.

查询到有些回答提到,必须使用urllib.parse.urlencode()函数将请求转换为字节,再因此如下:

data = urllib.parse.urlencode(data).encode("utf-8")
# 此时再进行url请求
request = urllib.request.Request(url, data, header)

但这对json数据格式无效,发生新的错误:

TypeError: not a valid non-string sequence or mapping object

原因:json.dumps(data)只是将数组/字典转换为字符串,urllib.parse.urlencode函数无效,当要转换作为url参数传递的字符串(即:将空格字符转换为“%20”)时,使用urlencode ,此方法的输出是字符串,而不是字节数组。

正确解决方案

json.dumps()返回一个字符串,因此必须调用json.dumps().encode()将其转换为字节数组。

# data = urllib.parse.urlencode(data).encode("utf-8")
data = json.dumps(formdata).encode()

此时运行,问题解决。

b'[{"predict":[16.302953720092773]}]'