python - 雅虎天气 API 2019 - 类型错误/属性错误
问题描述
想要在 Python 3.5.3 中在 Raspberry Pi 上运行 Yahoo 2019 Weather API。
通过成功运行 2.7.10 的 Yahoo 示例代码来验证 Yahoo 访问代码。
Ran 2to3 转换并收到以下脚本 TypeError 指示:
#Weather API Python sample code**
#Copyright 2019 Oath Inc. Licensed under the terms of the zLib license see
#https://opensource.org/licenses/Zlib for terms.**
#$ python --version**
#Python 2.7.10 - AFTER 2TO 3 CONVERSION**
import time, uuid, urllib.request, urllib.parse, urllib.error, urllib.request, urllib.error, urllib.parse
import hmac, hashlib
from base64 import b64encode
#Basic info
url = 'https://weather-ydn-yql.media.yahoo.com/forecastrss'
method = 'GET'
app_id = 'XXX'
consumer_key = 'XXX'
consumer_secret = 'XXX'
concat = '&'
query = {'location': 'sunnyvale,ca', 'format': 'json'}
oauth = {
'oauth_consumer_key': consumer_key,
'oauth_nonce': uuid.uuid4().hex,
'oauth_signature_method': 'HMAC-SHA1',
'oauth_timestamp': str(int(time.time())),
'oauth_version': '1.0'
}
#Prepare signature string (merge all params and SORT them)
merged_params = query.copy()
merged_params.update(oauth)
sorted_params = [k + '=' + urllib.parse.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
signature_base_str = method + concat + urllib.parse.quote(url, safe='') + concat + urllib.parse.quote(concat.join(sorted_params), safe='')
#Generate signature
composite_key = urllib.parse.quote(consumer_secret, safe='') + concat
oauth_signature = b64encode(hmac.new(composite_key, signature_base_str, hashlib.sha1).digest())
#Prepare Authorization header
oauth['oauth_signature'] = oauth_signature
auth_header = 'OAuth ' + ', '.join(['{}="{}"'.format(k,v) for k,v in oauth.items()])
#Send request
url = url + '?' + urllib.parse.urlencode(query)
request = urllib.request.Request(url)
request.add_header('Authorization', auth_header)
request.add_header('X-Yahoo-App-Id', app_id)
response = urllib.request.urlopen(request).read()
print(response)
ERROR:
pi@raspberrypi:~/Weather $ python3 yahoo2TO3.py
Traceback (most recent call last):
File "yahoo2.py", line 41, in <module>
oauth_signature = b64encode(hmac.new(composite_key, signature_base_str, hashlib.sha1).digest())
File "/usr/lib/python3.5/hmac.py", line 144, in new
return HMAC(key, msg, digestmod)
File "/usr/lib/python3.5/hmac.py", line 42, in __init__
raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
TypeError: key: expected bytes or bytearray, but got 'str'
试了3.7代码样例,收到AttributeError:
#Weather API Python sample code
#Copyright 2019 Oath Inc. Licensed under the terms of the zLib license see #https://opensource.org/licenses/Zlib for terms.
#$ python --version
#Python 3.7.x
import time, uuid, urllib, json
import hmac, hashlib
from base64 import b64encode
#Basic info
app_id = 'XXX'
consumer_key = 'XXX'
consumer_secret = 'XXX'
query = {'location': 'macau,mo', 'format': 'json', 'u': 'c'}
url = 'https://weather-ydn-yql.media.yahoo.com/forecastrss'
method = 'GET'
concat = '&'
oauth = {
'oauth_consumer_key': consumer_key,
'oauth_nonce': uuid.uuid4().hex,
'oauth_signature_method': 'HMAC-SHA1',
'oauth_timestamp': str(int(time.time())),
'oauth_version': '1.0'
}
#Prepare signature string (merge all params and SORT them)
merged_params = query.copy()
merged_params.update(oauth)
sorted_params = [k + '=' + urllib.parse.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
signature_base_str = method + concat + urllib.parse.quote(url, safe='') + concat + urllib.parse.quote(concat.join(sorted_params), safe='')
#Generate signature
composite_key = urllib.parse.quote(consumer_secret, safe='') + concat
oauth_signature = b64encode(hmac.new(composite_key.encode('utf-8'), signature_base_str.encode('utf-8'), hashlib.sha1).digest())
#Prepare Authorization header
oauth['oauth_signature'] = oauth_signature.decode('utf-8')
auth_header = 'OAuth ' + ', '.join(['{}="{}"'.format(k,v) for k,v in oauth.items()])
#Send request
url = url + '?' + urllib.parse.urlencode(query)
request = urllib.request.Request(url)
request.headers['Authorization'] = auth_header
request.headers['X-Yahoo-App-Id']= app_id
response = urllib.request.urlopen(request).read()
print(response)
ERROR:
pi@raspberrypi:~/Weather3 $ python3 yahoo3.py
Traceback (most recent call last):
File "yahoo3.py", line 34, in <module>
sorted_params = [k + '=' + urllib.parse.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
File "yahoo3.py", line 34, in <listcomp>
sorted_params = [k + '=' + urllib.parse.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
AttributeError: module 'urllib' has no attribute 'parse'
请求帮助以在 3.5 中运行其中一个或另一个。
解决方案
已解决:在 Python 3.7 的示例代码中,将标头更改import urllib
为import urllib.request
. 进行此更改后,使用 Raspberry Pi Python 3.5.3 即可正常工作。
推荐阅读
- node.js - JWT 令牌不特定于用户
- java - 休眠:来自 HqlSqlWalker 的 NullPointerException
- algorithm - 在计算它们的接近程度后从 3 个值中选择 2 个或 3 个值的算法
- postgresql - React-admin:dataProvider 抛出错误。它应该返回一个被拒绝的 Promise。- 尝试在 pg 数据库中设置参照完整性
- complexity-theory - O(n*log n) + O(m*log m) 与 O((n+m)log(n+m))
- javascript - 反应firebase自定义字段身份验证创建用户未将自定义字段存储在firestore数据库集合中
- java - java.io.IOException:流已关闭!ADLS Gen 2 中的 HDInsight 错误
- entity-framework - 实体框架嵌套查询
- asp.net-mvc - MVC 问题与在第三个中实现的 2 个不同 SQL 表中的级联下拉列表
- split - 拆分字符串并隐蔽浮动