python urllib.request.request参数'data'对象类型



我尝试使用 urllib.request.request.request (Python 3.6.7)来对内部Web服务进行API调用,以获得一些JSON结果。我需要将一些数据和标头发送到服务器,因此我使用 urllib.request.request.request 类来执行此操作。对于 data 的输入,我尝试找出它将接受的格式。从Python文档中说:

受支持的对象类型包括字节,类似文件的对象和 Iterables

因此,我使用 dictionary 数据类型进行此参数 data 。这是我的代码:

import urllib
my_url = "https://httpbin.org/post"
my_headers = { "Content-Type" : "application/x-www-form-urlencoded" }
my_data = {
        "client_id" : "ppp",
        "client_secret" : "000",
        "grant_type" : "client_credentials" }
req = urllib.request.Request(url=my_url, data=my_data, headers=my_headers)
response = urllib.request.urlopen(req)
html = response.read()
print(html)

我得到这样的错误:

Traceback (most recent call last):
  File "./callapi.py", line 23, in <module>
    response = urllib.request.urlopen(req)
  File "/usr/lib64/python3.6/urllib/request.py", line 223, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib64/python3.6/urllib/request.py", line 526, in open
    response = self._open(req, data)
  File "/usr/lib64/python3.6/urllib/request.py", line 544, in _open
    '_open', req)
  File "/usr/lib64/python3.6/urllib/request.py", line 504, in _call_chain
    result = func(*args)
  File "/usr/lib64/python3.6/urllib/request.py", line 1361, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "/usr/lib64/python3.6/urllib/request.py", line 1318, in do_open
    encode_chunked=req.has_header('Transfer-encoding'))
  File "/usr/lib64/python3.6/http/client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib64/python3.6/http/client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib64/python3.6/http/client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib64/python3.6/http/client.py", line 1064, in _send_output
    + b'rn'
TypeError: can't concat str to bytes

i然后在此文档页面中遵循示例,然后将我的代码更改为:

import urllib
my_url = "https://httpbin.org/post"
my_headers = { "Content-Type" : "application/x-www-form-urlencoded" }
my_data = {
        "client_id" : "ppp",
        "client_secret" : "000",
        "grant_type" : "client_credentials" }
my_uedata = urllib.parse.urlencode(my_data)
my_edata = my_uedata.encode('ascii')
req = urllib.request.Request(url=my_url, data=my_edata,headers=my_headers)
response = urllib.request.urlopen(req)
html = response.read()
print(html)

然后起作用。

我的问题是,不是在文档中说此类接受数据类型 iterables 吗?为什么我的参数 dict 是错误的?我的最终结果是工作使用 str.Encode()返回字节对象的方法,看来该类必须取字字节对象而不是迭代对象。

我试图将Python标准库文档作为Python中代码的主要参考来源文档有效,或者如果还有其他教程,我需要通过更好的方式使用它。谢谢。

我同意您的看法,DOC并不明确。隐含的是,如果data参数是一种疑问,则必须是字节的一个可观的。当我尝试将字符串作为数据传递时,我收到了一个明确的错误消息:

typeError:发布数据应为字节,字节或文件对象。它不能是类型str。

因此,出于这个原因,峰值不能是字典。作为有效迭代的一个景象,在不是字节对象中(好的,只是一个示例,没有理由在真实代码中使用它...):

def dict_iter(d):
    for i in d.items():
        yield(str(i).encode())

您可以将该发电机用于data参数:

req = urllib.request.Request(url=my_url, data=dict_iter(my_data), headers=my_headers)

最新更新