gweather.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #!/usr/bin/python
  2. import urllib
  3. from xml.etree.cElementTree import parse
  4. from datetime import datetime, timedelta
  5. import os
  6. from os.path import join
  7. from sys import argv
  8. try:
  9. import cPickle as pickle
  10. except ImportError:
  11. import pickle
  12. #Usage: yweather.py AYXX0001 Celsius
  13. if len(argv) != 3:
  14. raise Exception('Usage: yweather.py zip_code units. zip_code is your city code in Yahoo Weather, units can be Celsius or Fahrenheit.')
  15. else:
  16. zip_code = argv[1]
  17. if argv[2] == 'Fahrenheit' or argv[2] == 'fahrenheit':
  18. units = 'f'
  19. else:
  20. units = 'c'
  21. CACHE_HOURS = 6
  22. #http://weather.yahooapis.com/forecastrss
  23. WEATHER_URL = 'http://xml.weather.yahoo.com/forecastrss?p=%s&u=%s'
  24. WEATHER_NS = 'http://xml.weather.yahoo.com/ns/rss/1.0'
  25. def weather_for_zip(zip_code, units):
  26. url = WEATHER_URL % (zip_code, units)
  27. rss = parse(urllib.urlopen(url)).getroot()
  28. forecasts = []
  29. for element in rss.findall('channel/item/{%s}forecast' % WEATHER_NS):
  30. forecasts.append(dict(element.items()))
  31. ycondition = rss.find('channel/item/{%s}condition' % WEATHER_NS)
  32. return {
  33. 'current_condition': dict(ycondition.items()),
  34. 'forecasts': forecasts,
  35. 'title': rss.findtext('channel/title'),
  36. 'pubDate': rss.findtext('channel/item/pubDate'), #rss.findtext('channel/lastBuildDate'),
  37. 'location': dict(rss.find('channel/{%s}location' % WEATHER_NS).items()),
  38. 'wind': dict(rss.find('channel/{%s}wind' % WEATHER_NS).items()),
  39. 'atmosphere': dict(rss.find('channel/{%s}atmosphere' % WEATHER_NS).items()),
  40. 'astronomy': dict(rss.find('channel/{%s}astronomy' % WEATHER_NS).items()),
  41. 'units': dict(rss.find('channel/{%s}units' % WEATHER_NS).items())
  42. }
  43. def print_openbox_pipe_menu(weather):
  44. print '<openbox_pipe_menu>'
  45. print '<separator label="%s %s" />' % (weather['location']['city'],weather['pubDate'])
  46. print '<separator label="Current conditions" />'
  47. print '<item label="Weather: %s" />' % weather['current_condition']['text']
  48. print '<item label="Temperature: %s %s" />' % ( weather['current_condition']['temp'],
  49. weather['units']['temperature'] )
  50. print '<item label="Humidity: %s%%" />' % weather['atmosphere']['humidity']
  51. print '<item label="Visibility: %s %s" />' % ( weather['atmosphere']['visibility'],
  52. weather['units']['distance'] )
  53. #pressure: steady (0), rising (1), or falling (2)
  54. if weather['atmosphere']['rising'] == 0:
  55. pressure_state = 'steady'
  56. elif weather['atmosphere']['rising'] == 1:
  57. pressure_state = 'rising'
  58. else:
  59. pressure_state = 'falling'
  60. print '<item label="Pressure: %s %s (%s)" />' % ( weather['atmosphere']['pressure'],
  61. weather['units']['pressure'], pressure_state )
  62. print '<item label="Wind chill: %s %s" />' % ( weather['wind']['chill'],
  63. weather['units']['temperature'] )
  64. print '<item label="Wind direction: %s degrees" />' % weather['wind']['direction']
  65. print '<item label="Wind speed: %s %s" />' % ( weather['wind']['speed'],
  66. weather['units']['speed'] )
  67. print '<item label="Sunrise: %s" />' % weather['astronomy']['sunrise']
  68. print '<item label="Sunset: %s" />' % weather['astronomy']['sunset']
  69. for forecast in weather['forecasts']:
  70. print '<separator label="Forecast: %s" />' % forecast['day']
  71. print '<item label="Weather: %s" />' % forecast['text']
  72. print '<item label="Min temperature: %s %s" />' % ( forecast['low'],
  73. weather['units']['temperature'] )
  74. print '<item label="Max temperature: %s %s" />' % ( forecast['high'],
  75. weather['units']['temperature'] )
  76. print '</openbox_pipe_menu>'
  77. cache_file = join(os.getenv("HOME"), '.yweather.cache')
  78. try:
  79. f = open(cache_file,'rb')
  80. cache = pickle.load(f)
  81. f.close()
  82. except IOError:
  83. cache = None
  84. if cache == None or (zip_code, units) not in cache or (
  85. cache[(zip_code, units)]['date'] + timedelta(hours=CACHE_HOURS) < datetime.utcnow()):
  86. # The cache is outdated
  87. weather = weather_for_zip(zip_code, units)
  88. if cache == None:
  89. cache = dict()
  90. cache[(zip_code, units)] = {'date': datetime.utcnow(), 'weather': weather}
  91. #Save the data in the cache
  92. try:
  93. f = open(cache_file, 'wb')
  94. cache = pickle.dump(cache, f, -1)
  95. f.close()
  96. except IOError:
  97. raise
  98. else:
  99. weather = cache[(zip_code, units)]['weather']
  100. print_openbox_pipe_menu(weather)