RE: Help with a Python Program

  • From: "Ken Perry" <whistler@xxxxxxxxxxxxx>
  • To: <programmingblind@xxxxxxxxxxxxx>
  • Date: Mon, 6 Oct 2008 22:28:14 -0500

 
 
This is pretty easy to do.  Unfortunately I am extremely busy right this
minute.  However if no one gets to you till Wednesday I will get to it.  
Ken
 

  _____  

From: programmingblind-bounce@xxxxxxxxxxxxx
[mailto:programmingblind-bounce@xxxxxxxxxxxxx] On Behalf Of BlueScale
Sent: Sunday, October 05, 2008 10:39 PM
To: programmingblind@xxxxxxxxxxxxx
Subject: Help with a Python Program


Hi,
I found this program to get the weather with a commandline program.  I want
to modify it for use inside another program, but every time I do anything to
it I end up breaking it.  I am still very new at Python.  I would like it
simplified quite a bit.  All I need is a variable set at the top with a 5
digit zipcode, so it is easy to modify.  I would like it to only return the
current temp followed by the current condition.  For example, when ran it
should return something like 78F | cloudy.  I need to remove the extended
forecast and the commandline arguments.  Can someone please help with this
and send me some info on how it was done? I thought it would be easy to do
but apparently I was wrong. *grin*  It would be even better if the whole
program could be simplified down to one function, but I am not sure that
will be possible.
Thanks for the help, and here is the code:
#! /usr/bin/python

"""
Fetches weather reports from Yahoo!

Written by Thomas Upton (http://thomas.fiveuptons.com/),
with contributions from Chris Lasher (http://igotgenes.blogspot.com/).

This code is licensed under a BY-NC-SA Creative Commons license.
http://creativecommons.org/licenses/by-nc-sa/3.0/us/
"""

import sys
import urllib
from optparse import OptionParser
from xml.dom.minidom import parse

# Yahoo!'s limit on the number of days they will forecast for
DAYS_LIMIT = 2
WEATHER_URL = 'http://xml.weather.yahoo.com/forecastrss?p=%s'
WEATHER_NS = 'http://xml.weather.yahoo.com/ns/rss/1.0'

def get_weather(zip_code, days):
  """
  Fetches weather report from Yahoo!

  :Parameters:
  -`zip_code`: A five digit US zip code.
  -`days`: number of days to obtain forecasts for

  :Returns:
  -`weather_data`: a dictionary of weather data

  """

  # Get the correct weather url.
  url = WEATHER_URL % zip_code

  # Parse the XML feed.
  dom = parse(urllib.urlopen(url))

  # Get the units of the current feed.
  yunits = dom.getElementsByTagNameNS(WEATHER_NS, 'units')[0]

  # Get the location of the specified zip code.
  ylocation = dom.getElementsByTagNameNS(WEATHER_NS, 'location')[0]

  # Get the currrent conditions.
  ycondition = dom.getElementsByTagNameNS(WEATHER_NS, 'condition')[0]

  # Hold the forecast in a hash.
  forecasts = []

  # Walk the DOM in order to find the forecast nodes.
  for i, node in enumerate(
          dom.getElementsByTagNameNS(WEATHER_NS,'forecast')):
      # Stop if the number of obtained forecasts equals the number of
requested days
      if i + 1 > days:
          break
      else:
          # Insert the forecast into the forcast dictionary.
          forecasts.append (
              {
                  'date': node.getAttribute('date'),
                  'low': node.getAttribute('low'),
                  'high': node.getAttribute('high'),
                  'condition': node.getAttribute('text')
              }
          )

  # Return a dictionary of the weather that we just parsed.
  weather_data = {
      'current_condition': ycondition.getAttribute('text'),
      'current_temp': ycondition.getAttribute('temp'),
      'forecasts': forecasts,
      'units': yunits.getAttribute('temperature'),
      'city': ylocation.getAttribute('city'),
      'region': ylocation.getAttribute('region'),
  }
  
  return weather_data

def create_report(weather_data, options):
  """
  Constructs a weather report as a string.

  :Parameters:
  -`weather_data`: a dictionary of weather data
  -`options`: options to determine output selections

  :Returns:
  -`report_str`: a formatted string reporting weather

  """

  report = []
  
  if options.location:
      if options.verbose:
          # Add the location header.
          report.append("Location:")

      # Add the location.
      location_string = "%(city)s, %(region)s\n" % weather_data
      report.append(location_string)

  if (not options.nocurr):
      if options.verbose:
          # Add current conditions header.
          report.append("Current conditions:")

      # Add the current weather.
      currstr = "%(current_temp)s%(units)s | %(current_condition)s \n" %
weather_data
      report.append(currstr)

  if (options.forecast > 0):
    if options.verbose:
        # Add the forecast header.
        report.append("Forecast:")

    # Add the forecasts.
    for forecast in weather_data['forecasts']:
      
        forecast['units'] = weather_data['units']
      
        forecast_str = """\
  %(date)s
    Low: %(low)s%(units)s
    High: %(high)s%(units)s
    Condition: %(condition)s
  """ % forecast

        report.append(forecast_str)

  report_str = "\n".join(report)
  
  return report_str

def create_cli_parser():
  """Creates a command line interface parser."""

  usage = (
      "%prog [options] zip_code",
      __doc__,
      """\
Arguments:
  ZIPCODE: The ZIP code for the region of interest.
"""
  )
  
  usage = "\n\n".join(usage)
  
  cli_parser = OptionParser(usage)
  
  # Add the CLI options
  cli_parser.add_option('-c', '--nocurr', action='store_true',
      help="Suppress reporting the current weather conditions"
  )
  
  cli_parser.add_option('-f', '--forecast', action='store', type='int',
      help="Show the forecast for DAYS days", metavar="DAYS")
  
  cli_parser.add_option('-l', '--location', action='store_true',
      help="Give the location of the weather"
  )
  
  cli_parser.add_option('-v', '--verbose', action='store_true',
      help="Print the weather section headers"
  )
  
  cli_parser.set_defaults(forecast=0)

  return cli_parser

def main(argv):

  # Create the command line parser.
  cli_parser = create_cli_parser()
  
  # Get the options and arguments.
  opts, args = cli_parser.parse_args(argv)

  # Check that an argument was passed.
  if len(args) < 1:
      cli_parser.error("Not enough arguments supplied.")

  # Check the zip code
  zip_code = args[0]
  
  if len(zip_code) != 5 or not zip_code.isdigit():
      cli_parser.error("ZIP code must be 5 digits")
  
  if opts.forecast > DAYS_LIMIT or opts.forecast < 0:
     cli_parser.error("Days to forecast must be between 0 and %d" %
DAYS_LIMIT)

  # Get the weather.
  weather = get_weather(zip_code, opts.forecast)

  # Create the report.
  report = create_report(weather, opts)

  print report

if __name__ == "__main__":
  main(sys.argv[1:]) 

Other related posts: