このエントリーをはてなブックマークに追加
facebooktwittergoogle_plusredditpinterestlinkedinmail

こんにちは、tapunです。

昨日、Raspberry Pi に天気予報を喋ってもらう設定をしました。

We can dream...Guy Hagi - Channel 9 Hawaii's Severe Weather


課題

昨日はエラーなく天気予報を喋ってくれていたのですが、今日になってtalk_weather.pyを実行すると下記のようなエラーが返ってくるようになりました。

$ python weather_talk.py
jsay 12月5日、12時55分31秒
Traceback (most recent call last):
  File "talk_weather.py", line 70, in <module>
    main()
  File "talk_weather.py", line 16, in main
    say_weather()
  File "talk_weather.py", line 46, in say_weather
    today_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])
TypeError: 'NoneType' object has no attribute '__getitem__'

これでは日時しか喋ってもらえません。

原因は?

 

question mark

ちょっとね、プログラミング出来ないのでよく分かんないですが、最高気温と最低気温のところが問題のようです。

もう一度お天気Webサービスの仕様を見てみると、サンプルでも気温は”null”が返ってきていますね。

   "forecasts" : [
      {
         "dateLabel" : "今日",
         "telop" : "晴のち曇",
         "date" : "2013-01-29",
         "temperature" : {
            "min" : null,
            "max"  : {
               "celsius" : "11",
               "fahrenheit" : "51.8"
            }



暫定的な回避策

nullが返ってきたら別のテキストを出力したり、nullに何か代入できるといいんですけど、残念ながらその知識がないので一旦天気予報と気温予測を分けてjsayコマンドで喋らせるようにします。 :roll: 

talk_weather2.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import shlex
import subprocess

from datetime import datetime

import urllib2
import json

CMD_SAY = 'jsay'

def main():
    say_datetime()
    say_weather()
    say_temperature()
    return

def say_datetime():
    d = datetime.now()
    text = '%s月%s日、%s時%s分%s秒' % (d.month, d.day, d.hour, d.minute, d.second)
    text = CMD_SAY + ' ' + text
    print text
    proc = subprocess.Popen(shlex.split(text))
    proc.communicate()
    return

def say_weather():
    city = '130010'; # Tokyo
    json_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' #API URL

    weather_text = u'%sの天気は%sです。'

    try:
        r = urllib2.urlopen('%s?city=%s' % (json_url, city) )
        obj = json.loads( unicode(r.read()) )

        title = obj['title']
        forecasts = obj['forecasts']

        # TODAY
        cast = forecasts[0]
        temperature = cast['temperature']
        today_w_txt = weather_text % (cast['dateLabel'], cast['telop'])

        # TOMMOROW
        cast = forecasts[1]
        temperature = cast['temperature']
        tommorow_w_txt = weather_text % (cast['dateLabel'], cast['telop'])

        # SAY
        weather_str = title + ' ' + today_w_txt  + ' ' + tommorow_w_txt
        weather_str = weather_str.encode('utf-8')

        text = '''%s '%s' ''' % (CMD_SAY, weather_str)
        print text
        proc = subprocess.Popen(shlex.split(text))
        proc.communicate()
    finally:
        r.close()

    return

def say_temperature():
    city = '130010'; # Tokyo
    json_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' #API URL

    temperature_text = u'%sの予想最高気温、%s度、予想最低気温、%s度です。'

    try:
        r = urllib2.urlopen('%s?city=%s' % (json_url, city) )
        obj = json.loads( unicode(r.read()) )

        title = obj['title']
        forecasts = obj['forecasts']

        # TODAY
        cast = forecasts[0]
        temperature = cast['temperature']
        today_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])

        # TOMMOROW
        cast = forecasts[1]
        temperature = cast['temperature']
        tommorow_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])

        # SAY
        temperature_str = title + ' ' + today_t_txt +  ' ' + tommorow_t_txt
        temperature_str = weather_str.encode('utf-8')

        text = '''%s '%s' ''' % (CMD_SAY,  temperature_str)
        print text
        proc = subprocess.Popen(shlex.split(text))
        proc.communicate()
    finally:
        r.close()

    return

### Execute
if __name__ == "__main__":
    main()

 これで、実行してみます。

$ python talk_weather2.py
jsay 12月5日、19時44分18秒
jsay '東京都 東京 の天気 今日の天気は晴れです。 明日の天気は晴のち曇です。'
Traceback (most recent call last):
  File "talk_weather2.py", line 105, in <module>
    main()
  File "talk_weather2.py", line 17, in main
    say_temperature()
  File "talk_weather2.py", line 83, in say_temperature
    today_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])
TypeError: 'NoneType' object has no attribute '__getitem__'

 一応天気まで喋ってくれるようになったので、今日のところはこれでよしとします。

まとめ

nullが返ってきたときに「気温の情報は取得できませんでした」と言って欲しいのですが、pythonの知識がなくて書けません!

ちょっと趣味として勉強しようかしら・・・

もし書き方が分かる人がいらっしゃったら、ご教授いただけると嬉しいです!!!

Please?



 


Raspberry Pi ブログランキングへ