Yahoo Weather API 2019 — ошибка типа / ошибка атрибута

#python #python-3.x #yahoo-weather-api

#питон #python-3.x #yahoo-погода-api #python #yahoo-weather-api

Вопрос:

Хочу запустить Yahoo 2019 Weather API на Raspberry Pi на Python 3.5.3.
Проверил коды доступа Yahoo, успешно запустив пример кода Yahoo для 2.7.10.

Весь пример кода взят из: https://gist.github.com/VerizonMediaOwner/e6be950f74c5a8071329f1d9a50e3158#file-weather_ydn_sample-py

Запустил преобразование 2to3 и получил следующий скрипт, указанный в ошибке типа:

 #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 = 'amp;'
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 и получил ошибку атрибута:

 #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 = 'amp;'
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.

Комментарии:

1. Почему вы не используете запросы в качестве клиентской библиотеки HTTP? Смотрите docs.python-requests.org/en/master

2. Я считаю, что ваше предложение является правильным направлением. Я добавил библиотеку запросов в свой Python 3 и ‘import requests’ в заголовок тестового файла. Я исследовал и перепробовал множество конфигураций, но продолжаю получать ‘ошибка типа: ‘объект кортежа’не вызывается’. Это может быть связано с попыткой передать три кода безопасности Id, ключ и секрет для доступа к файлу?

Ответ №1:

РЕШЕНО: в примере кода для Python 3.7 измените заголовок import urllib на import urllib.request . После этого изменения он работает просто отлично, используя Raspberry Pi Python 3.5.3.