Python urllib.request.Request параметр 'data' тип объекта
Я пытаюсь использовать urllib.request.Request (Python 3.6.7), чтобы вызвать API для внутренних веб-сервисов, чтобы получить некоторые результаты JSON. Мне нужно отправить некоторые данные и заголовки на сервер, поэтому я использую класс urllib.request.Request для этого. Для ввода данных я стараюсь выяснить, в каком формате он будет принимать. Из документов Python сказано:
Поддерживаемые типы объектов включают байты, файловые объекты и итерации.
Поэтому я использую тип данных словаря для данных этого параметра. Вот мой код:
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'\r\n'
TypeError: can't concat str to bytes
Затем я следую примеру на этой странице документации и изменяю свой код на:
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)
тогда это работает.
У меня такой вопрос, не указано ли в документации, что этот класс принимаетитерируемые типы данных? почему мой параметр в dict неверен? Мой окончательный результат - использование метода str.encode(), который возвращает байтовый объект, и кажется, что этот класс должен принимать байтовый объект, а не итерируемый объект.
Я пытаюсь использовать документы стандартной библиотеки Python в качестве основного источника ссылки на код в Python, однако мне трудно его использовать, надеюсь, кто-нибудь сможет пролить свет на то, чтобы помочь мне понять больше о том, как работает библиотека документов, или, если есть какой-то другой учебник, мне нужно пройти, прежде чем я смогу использовать его лучше. Благодарю.
1 ответ
Я согласен с вами, документ не является явным. Подразумевается, что если data
Параметр является итерируемым, он должен быть итерируемым из байтов. Когда я попытался передать строку как данные, я получил явное сообщение об ошибке:
Ошибка TypeEr: данные POST должны быть байтами, итерируемыми байтами или файловым объектом. Это не может быть типа ул.
По этой причине повторяемое не может быть словарем. В качестве примера действительного итерируемого объекта, который не является байтовым объектом (хорошо, просто пример, нет причин использовать это в реальном коде...):
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)