urlopen: AttributeError: объект 'bytes' не имеет атрибута 'timeout'

Я пытаюсь открыть файл json из API, содержащий символы польского алфавита. Я попытался закодировать URL-адрес в utf-8, но все еще возникают проблемы. Я включаю написанный мной код и появившуюся ошибку.

import urllib.request as request
import json
url='https://api.um.warszawa.pl/api/action/dbtimetable_get?id=myapiID&busstopId=wartość&busstopNr=wartość&line=wartość&apikey=wartość'
url=url.encode('utf-8')
with request.urlopen(url) as response:
    source = response.read()
    data = json.loads(source)

Затем появляется ошибка: объект «байты» не имеет атрибута «тайм-аут».


person DAVID LOBO    schedule 17.09.2020    source источник
comment
опубликуйте полную трассировку. ты на питоне 2 или 3?   -  person Paul H    schedule 17.09.2020
comment
Не могли бы вы также попробовать опубликовать результат печати объекта, который, по его словам, не имеет атрибута «тайм-аут»?   -  person swarles-barkley    schedule 17.09.2020
comment
Это интересно ... здесь кто-то, похоже, решил, что stackoverflow.com/questions/1916684/. Но я попробовал вашу версию, и у меня тоже timeout ошибка: AttributeError: 'bytes' object has no attribute 'timeout'. Я попытался настроить его с помощью специального класса: class StringWithTimeout(str): def __new__(cls, string, timeout): obj = str.__new__(cls, string) setattr(obj, 'timeout', timeout) return obj. Но потом я получаю URLError: <urlopen error unknown url type: b'https>   -  person deponovo    schedule 17.09.2020
comment
Какую версию Python вы используете?   -  person deponovo    schedule 17.09.2020
comment
Я использую python 3.7.3 @deponovo   -  person DAVID LOBO    schedule 18.09.2020


Ответы (1)


Здесь есть две проблемы, вероятно, обе проистекающие из требования доступа к URL-адресу с компонентами запроса, которые включают символы, отличные от ASCII.

  • Во-первых, передача экземпляра bytes в urlopen приведет к неожиданному поведению, как описано здесь
  • Во-вторых, символы, отличные от ASCII, в параметрах запроса URL-адреса не допускаются, поэтому параметры запроса должны быть закодированы по URL-адресу.

Итак, учитывая неверный URL-адрес, вам нужно сделать что-то вроде этого:

import json
from urllib import parse
from urllib import request

parts - parse.urlsplit(url)
query_dict = parse.parse_qs(parts.query)
encoded_query = parse.urlencode(query_dict)
fixed_url = parse.urlunsplit((parts.scheme, parts.netloc, parts.path, encoded_query, parts.fragment))
response = request.urlopen(fixed_url)

print(json.load(response))
person snakecharmerb    schedule 17.09.2020
comment
Спасибо за предложение @snakecharmerb. Я попробовал и, похоже, возникла проблема с нестроковой последовательностью или объектом сопоставления. Для подробностей я включаю точную ошибку. # non-empty strings will fail this 890 if len(query) and not isinstance(query[0], tuple): --> 891 raise TypeError 892 # Zero-length sequences of all types will get here and succeed, 893 # but that's a minor nit. Since the original implementation TypeError: not a valid non-string sequence or mapping object - person DAVID LOBO; 18.09.2020
comment
Извините, я пропустил шаг в ответе. Теперь он должен работать. - person snakecharmerb; 19.09.2020