【问题标题】:urlopen: AttributeError: 'bytes' object has no attribute 'timeout'urlopen:AttributeError:“字节”对象没有属性“超时”
【发布时间】:2020-09-17 16:12:16
【问题描述】:

我正在尝试从包含波兰字母表字符的 API 打开一个 json 文件。我试图将 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)

然后出现错误:'bytes' object has no attribute 'timeout'。

【问题讨论】:

  • 发布完整的回溯。你在 python 2 还是 3 上?
  • 您是否也可以尝试发布打印它说没有属性“超时”的对象的结果?
  • 这很有趣......这里似乎有人已经解决了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>
  • 你用的是哪个python版本?
  • 又一个潜在的解决方案stackoverflow.com/questions/36395705/…

标签: python character-encoding urlencode non-ascii-characters


【解决方案1】:

这里有两个问题,可能都源于需要访问包含非 ASCII 字符的查询组件的 url。

  • 首先,将bytes 实例传递给urlopen 将导致意外行为,如here 所述
  • 其次,不允许在 URL 的查询参数中使用非 ASCII 字符,因此必须对查询参数进行 urlencoded。

所以给定无效的 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))

【讨论】:

  • 感谢@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
  • 对不起,我错过了答案中的一步。它现在应该可以工作了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-29
  • 2020-03-11
  • 2016-11-09
  • 2021-09-26
  • 2016-11-02
相关资源
最近更新 更多