Import the PyOWM library

As simple as:

>>> from pyowm import OWM

Create global OWM object

Use your OWM API key if you have one (read here on how to obtain an API key). By default, if you don’t specify which API subscription type you want to use, a free-subscription OWM global object is instantiated:

>>> API_key = 'G097IueS-9xN712E'
>>> owm = OWM(API_key)

Of course you can change your API key at a later time if you need:

>>> owm.get_API_key()
'G09_7IueS-9xN712E'
>>> owm.set_API_key('6Lp$0UY220_HaSB45')

The same happens with the language: you can speficy in which language the OWM Weather API will return textual data of weather queries. Language is specified by passing its corresponding two-characters string, eg: es, sk, etc. The default language is English (en):

>>> owm_en = OWM()              # default language is English
>>> owm_ru = OWM(language='ru') # Russian

You can obtain the OWM global object related to a specific OWM Weather API version, just specify it after the API key parameter(check before that the version is supported!):

>>> owm = OWM(API_key='abcdef', version='2.5')

If you don’t specify an API version number, you’ll be provided with the OWM object that represents the latest available OWM Weather API version.

Advanced users might want to inject into the library a specific configuration: this can be done by injecting the Python path of your personal configuration module as a string into the library instantiation call like this:

>>> owm = OWM(API_key='abcdef', version='2.5', config_module='mypackage.mysubpackage.myconfigmodule')

Be careful! You must provide a well-formatted configuration module for the library to work properly and your module must be in your PYTHONPATH. More on configuration modules formatting can be found here.

Using a paid (pro) API key subscription

If you purchased a pro subscription on the OWM Weather API, you can instantiate the global OWM like this:

>>> owm = pyowm.OWM('abcdef', subscription_type='pro')

When instantiating paid subscription OWM objects, you must provide an API key.

OWM Weather API version 2.5 usage examples

Setting a local cache provider

The PyOWM library comes with a built-in support for local caches: OWM Weather API reponses can be cached in order to save time and bandwidth. The default configuration uses no cache, however the library contains a built-in simple LRU cache implementation that can be plugged in by changing the configuration25.py module and specifying a LRUCache class instance:

...
# Cache provider to be used
from pyowm.caches.lrucache import LRUCache
cache = LRUCache()
...

By using the configuration25.py module, it is also possible to leverage external cache providers module, provided that they implement the interface that is expected by the library code.

Getting currently observed weather for a specific location.

Querying for current weather is simple: provide an OWM object with the location you want the current weather be looked up for and the job is done. You can specify the location either by passing its toponym (eg: “London”), the city ID (eg: 2643741) or its geographic coordinates (lon/lat):

obs = owm.weather_at_place('London,GB')                    # Toponym
obs = owm.weather_at_id(2643741)                           # City ID
obs = owm.weather_at_coords(-0.107331,51.503614)           # lat/lon

An Observation object will be returned, containing weather info about the location matching the toponym/ID/coordinates you provided. Be precise when specifying locations!

Retrieving city ID for a location

City IDs can be retrieved using a registry:

reg = owm.city_id_registry()
reg.ids_for('London')        # [ (123, 'London', 'GB'), (456, 'London', 'MA'), (789, 'London', 'WY')]
reg.locations_for("London")  # gives a list of Location instances
reg.geopoints_for("London")  # gives a list of pyowm.utils.geo.Point objects

You can pass the retrieved IDs with owm.weather_at_id method.

As multiple locations with the same name exist in different states, the registry comes with support for narrowing down queries on specific countries…

london = reg.ids_for('London', country='GB')                 # [ (123, 'London, GB') ]
london_loc = reg.locations_for('London', country='GB')       # [ <Location obj> ]
london_geopoint = reg.geopoints_for('London', country='GB')  # [ <Point obj> ]

… as well as for changing the type of matches between the provided string and the locations’ toponyms:

reg.ids_for("london", matching='exact')  # literal matching
reg.ids_for("london", matching='nocase') # case-insensitive
reg.ids_for("london", matching='like')   # substring search

Also remember that the registry can provide the geopoints (instances of pyowm.utils.geo.Point) corresponding to the searched toponyms:

list_of_geopoints = reg.geopoints_for('London', country='GB')

Please refer to the SW API docs for further detail.

Getting data from Observation objects

Observation objects store two useful objects: a Weather object that contains the weather-related data and a Location object that describes the location the weather data is provided for.

If you want to know when the weather observation data have been received, just call:

>>> obs.get_reception_time()                           # UNIX GMT time
1379091600L
>>> obs.get_reception_time(timeformat='iso')           # ISO8601
'2013-09-13 17:00:00+00'
>>> obs.get_reception_time(timeformat='date')          # datetime.datetime instance
datetime.datetime(2013, 09, 13, 17, 0, 0, 0)

You can retrieve the Weather object like this:

>>> w = obs.get_weather()

and then access weather data using the following methods:

>>> w.get_reference_time()                             # get time of observation in GMT UNIXtime
1377872206L
>>> w.get_reference_time(timeformat='iso')             # ...or in ISO8601
'2013-08-30 14:16:46+00'
>>> w.get_reference_time(timeformat='date')            # ...or as a datetime.datetime object
datetime.datetime(2013, 08, 30, 14, 16, 46, 0)

>>> w.get_clouds()                                     # Get cloud coverage
65

>>> w.get_rain()                                       # Get rain volume
{'3h': 0}

>>> w.get_snow()                                       # Get snow volume
{}

>>> w.get_wind()                                       # Get wind degree and speed
{'deg': 59, 'speed': 2.660}

>>> w.get_humidity()                                   # Get humidity percentage
67

>>> w.get_pressure()                                   # Get atmospheric pressure
{'press': 1009, 'sea_level': 1038.381}

>>> w.get_temperature()                                # Get temperature in Kelvin
{'temp': 293.4, 'temp_kf': None, 'temp_max': 297.5, 'temp_min': 290.9}
>>> w.get_temperature(unit='celsius')                  # ... or in Celsius degs
>>> w.get_temperature('fahrenheit')                    # ... or in Fahrenheit degs

>>> w.get_status()                                     # Get weather short status
'clouds'
>>> w.get_detailed_status()                           # Get detailed weather status
'Broken clouds'

>>> w.get_weather_code()                               # Get OWM weather condition code
803

>>> w.get_weather_icon_name()                          # Get weather-related icon name
'02d'

>>> w.get_weather_icon_url()                          # Get weather-related icon URL
'http://openweathermap.org/img/w/02d.png'

>>> w.get_sunrise_time()                               # Sunrise time (GMT UNIXtime or ISO 8601)
1377862896L
>>> w.get_sunset_time('iso')                           # Sunset time (GMT UNIXtime or ISO 8601)
'2013-08-30 20:07:57+00'

Support to weather data interpretation and lists of OWM weather conditions, codes and icons can be found here.

As said, Observation objects also contain a Location object with info about the weather location:

>>> l = obs.get_location()
>>> l.get_name()
'London'
>>> l.get_lon()
-0.12574
>>> l.get_lat()
51.50863
>>> l.get_ID()
2643743

The last call returns the OWM city ID of the location - refer to the OWM API documentation for details.

Getting weather forecasts

The OWM Weather API currently provides weather forecasts that are sampled :

  • every 3 hours
  • every day (24 hours)

The 3h forecasts are provided for a streak of 5 days since the request time and daily forecasts are provided for a maximum streak of 14 days since the request time (but also shorter streaks can be obtained).

You can query for 3h forecasts for a location using:

# Query for 3 hours weather forecast for the next 5 days over London
>>> fc = owm.three_hours_forecast('London,uk')

You can query for daily forecasts using:

# Query for daily weather forecast for the next 14 days over London
>>> fc = owm.daily_forecast('London,uk')

and in this case you can limit the amount of days the weather forecast streak will contain by using the limit parameter:

# Daily weather forecast just for the next 6 days over London
>>> fc = owm.daily_forecast('London,uk', limit=6)

Both of the above calls return a Forecaster object. Forecaster objects contain a Forecast object, which has all the information about your weather forecast. If you need to manipulate the latter, just go with:

>>> f = fc.get_forecast()

A Forecast object encapsulates the Location object relative to the forecast and a list of Weather objects:

# When has the forecast been received?
>>> f.get_reception_time()                           # UNIX GMT time
1379091600L
>>> f.get_reception_time('iso')                      # ISO8601
'2013-09-13 17:00:00+00'
>>> f.get_reception_time('date')                     # datetime.datetime instance
datetime.datetime(2013, 09, 13, 17, 0, 0, 0)

# Which time interval for the forecast?
>>> f.get_interval()
'daily'

# How many weather items are in the forecast?
>>> len(f)
20

# Get Location
>>> f.get_location()
<pyowm.location.Location object at 0x01921DF0>

Once you obtain a Forecast object, reading the forecast data is easy - you can get the whole list of Weather objects or you can use the built-in iterator:

# Get the list of Weather objects...
>>> lst = f.get_weathers()

# ...or iterate directly over the Forecast object
>>> for weather in f:
      print (weather.get_reference_time('iso'),weather.get_status())
('2013-09-14 14:00:00+0','Clear')
('2013-09-14 17:00:00+0','Clear')
('2013-09-14 20:00:00+0','Clouds')

The Forecaster class provides a few convenience methods to inspect the weather forecasts in a human-friendly fashion. You can - for example - ask for the GMT time boundaries of the weather forecast data:

# When in time does the forecast begin?
>>> fc.when_starts()                                  # UNIX GMT time
1379090800L
>>> fc.when_starts('iso')                             # ISO8601
'2013-09-13 16:46:40+00'
>>> fc.when_starts('date')
datetime.datetime(2013, 09, 13, 16, 46, 40, 0)        # datetime.datetime instance

# ...and when will it end?
>>> fc.when_ends()                                    # UNIX GMT time
1379902600L
>>> fc.when_ends('iso')                               # ISO8601
'2013-09-23 02:16:40+00'
>>> fc.when_ends('date')                              # datetime.datetime instance
datetime.datetime(2013, 09, 13, 16, 46, 40, 0)

In example, you can ask the Forecaster instance to tell which is the weather forecast for a specific point in time. You can specify this time using a UNIX timestamp, an ISO8601-formatted string or a Python datetime.datetime object (all times must will be handled as GMT):

# Tell me the weather for tomorrow at this hour
>>> from datetime import datetime
>>> date_tomorrow = datetime(2013, 9, 19, 12, 0)
>>> str_tomorrow = "2013-09-19 12:00+00"
>>> unix_tomorrow = 1379592000L
>>> fc.get_weather_at(date_tomorrow)
<weather.Weather at 0x00DF75F7>
>>> fc.get_weather_at(str_tomorrow)
<weather.Weather at 0x00DF75F7>
>>> fc.get_weather_at(unix_tomorrow)
<weather.Weather at 0x00DF75F7>

You will be provided with the Weather sample that lies closest to the time that you specified. Of course this will work only if the specified time is covered by the forecast! Otherwise, you will be prompted with an error:

>>> fc.get_weather_at("1492-10-12 12:00:00+00")
pyowm.exceptions.not_found_error.NotFoundError: The searched item was not found.
Reason: Error: the specified time is not included in the weather coverage range

Keep in mind that you can leverage the convenience timeutils module’s functions to quickly build datetime objects:

>>> from pyowm import timeutils
>>> timeutils.tomorrow()                              # Tomorrow at this hour
datetime.datetime(2013, 9, 19, 12, 0)
>>> timeutils.yesterday(23, 27)                       # Yesterday at 23:27
datetime.datetime(2013, 9, 19, 12, 0)
>>> timeutils.next_three_hours()
datetime.datetime(2013, 9, 18, 15, 0)                 # 3 hours from now
>>> t = datetime.datetime(2013, 19, 27, 8, 47, 0)
>>> timeutils.next_three_hours(t)
datetime.datetime(2013, 19, 27, 11, 47, 0)            # 3 hours from a specific datetime

Other useful convenicence methods in class Forecaster are:

# Will it rain, be sunny, foggy or snow during the covered period?
>>> fc.will_have_rain()
True
>>> fc.will_have_sun()
True
>>> fc.will_have_fog()
False
>>> fc.will_have_clouds()
False
>>> fc.will_have_snow()
False

# Will it be rainy, sunny, foggy or snowy at the specified GMT time?
time = "2013-09-19 12:00+00"
>>> fc.will_be_rainy_at(time)
False
>>> fc.will_be_sunny_at(time)
True
>>> fc.will_be_foggy_at(time)
False
>>> fc.will_be_cloudy_at(time)
False
>>> fc.will_be_snowy_at(time)
False
>>> fc.will_be_sunny_at(0L)           # Out of weather forecast coverage
pyowm.exceptions.not_found_error.NotFoundError: The searched item was not found.
Reason: Error: the specified time is not included in the weather coverage range

# List the weather elements for which the condition will be:
# rain, sun, fog and snow
>>> fc.when_rain()
[<weather.Weather at 0x00DB22F7>,<weather.Weather at 0x00DB2317>]
>>> fc.when_sun()
[<weather.Weather at 0x00DB62F7>]
>> fc.when_clouds()
[<weather.Weather at 0x00DE22F7>]
>>> fc.when_fog()
[<weather.Weather at 0x00DC22F7>.]
>>> fc.when_snow()
[]                                   # It won't snow: empty list

# Get weather for the hottest, coldest, most humid, most rainy, most snowy
# and most windy days in the forecast
>>> fc.most_hot()
<weather.Weather at 0x00DB67D9>
>>> fc.most_cold()
<weather.Weather at 0x00DB62F7>
>>> fc.most_humid()
<weather.Weather at 0x00DB62F7>
>>> fc.most_rainy()
<weather.Weather at 0x00DB62F7>
>>> fc.most_snowy()
None                                 # No snow in the forecast
>>> fc.most_windy()
<weather.Weather at 0x00DB62F7>

When calling the will_be_*_at() methods you can specify either a UNIX timestamp, a datetime.datetime object or an ISO8601-formatted string (format: “YYYY-MM-DD HH:MM:SS+00”). A boolean value will be returned, telling if the queried weather condition will apply to the time you specify (the check will be performed on the Weather object of the forecast which is closest in time to the time value that you provided).

When calling the when_*() methods you will be provided with a sublist of the Weather objects list in into the Forecaster instance, with items having as weather condition the one the method queries for.

Note on weather forecast items reference timestamps

Sometimes - due to caching on the OWM API side - the weather objects returned inside a Forecast object may refer to timestamps in the recent past. In order to remove those outdated weather items from the forecast, you can do:

>>> fcst.actualize()

Note on weather history

Weather history retrieval is a paid OWM API feature.

Getting weather history on a location

Weather history on a specific toponym can be retrieved using:

>>> owm.weather_history_at_place('London,uk')
[ <weather.Weather at 0x00BF81A2>, <weather.Weather at 0x00BF81C8>, ... ]

A list of Weather objects is returned. You can can specify a time window in which you want the results to be filtered:

>>> owm.weather_history_at_place('London,uk', start=1379090800L, end=1379099800L)
>>> owm.weather_history_at_place('London,uk', '2013-09-13 16:46:40+00', '2013-09-13 19:16:40+00')
>>> from datetime import datetime
>>> owm.weather_history_at_place('London,uk', datetime(2013, 9, 13, 16, 46, 40), datetime(2013, 9, 13, 19, 16, 40))

The time boundaries can be expressed either as a UNIX timestamp, a datetime.datetime object or an ISO8601-formatted string (format: “YYYY-MM-DD HH:MM:SS+00”).

What said before also applies for city ID-based queries:

>>> owm.weather_history_at_id(12345, start=1379090800L, end=1379099800L)

Getting meteostation measurements history

Weather data measurements history for a specific meteostation is available in three sampling intervals: 'tick' (which stands for minutely), 'hour' and 'day'. The calls to be made are:

# Get tick historic data for station 39276, only 4 data items
>>> hist = owm.station_tick_history(39276, limit=4)
# Get hourly historic data for station 39276
>>> hist = owm.station_hour_history(39276)
# Get daily historic data for station 39276, only 10 data items
>>> hist = owm.station_day_history(39276, 10)

and all of them return a Historian object. As you can notice, the amount of data measurements returned can be limited usign the proper parameter: by default, all available data items are retrieved. Each data item is composed by a temperature sample, a humidity sample, a pressure sample, a rain volume sample and a wind speed sample.

Once you have a Historian instance, you can obtain its encapsulated StationHistory object, which is a databox containing the data:

>>> sh = his.get_station_history()

and query data directly on it:

>>> sh.get_station_ID()                   # Meteostation ID
39276
>>> sh.get_interval()                     # Data sampling interval
'tick'
>>> sh.get_reception_time()               # Timestamp when data was received (GMT UNIXtime, ISO8601
                                          # or datetime.datetime)
1377862896L
>>> sh.get_reception_time("iso")
'2013-08-30 20:07:57+00'
>>> sh.get_measurements()                 # Get historic data as a dict
{
    1362933983: {
         "temperature": 266.25,
         "humidity": 27.3,
         "pressure": 1010.02,
         "rain": None,
         "wind": 4.7
     },
    [...]
}

The last call gives you back a dictionary containing the historic weather data: the keys of the dictionary are the UNIX timestamps of data sampling and the values are dictionaries having a fixed set of keys (temperature, humidity, pressure, rain, wind) along with their corresponding numeric values.

If you have no specific need to handle the raw data by yourself, you can leverage the convenience methods provided by the Historian class:

# Get the temperature time series (in different units of measure)
>>> his.temperature_series()
[(1381327200, 293.4), (1381327260, 293.6), (1381327320, 294.4), ...]
>>> his.temperature_series(unit="celsius")
[(1381327200, 20.25), (1381327260, 20.45), (1381327320, 21.25), ...]
>>> his.temperature_series("fahrenheit")
[(1381327200, 68.45), (1381327260, 68.81), (1381327320, 70.25), ...]

# Get the humidity time series
>>> his.humidity_series()
[(1381327200, 27.3), (1381327260, 27.2), (1381327320, 27.2), ...]

# Get the atmospheric pressure time series
>>> his.pressure_series()
[(1381327200, 1010.02), (1381327260, 1010.23), (1381327320, 1010.79), ...]

# Get the rain volume time series
>>> his.rain_series()
[(1381327200, None), (1381327260, None), (1381327320, None), ...]

# Get the wind speed time series
>>> his.wind_series()
[(1381327200, 4.7), (1381327260, 4.7), (1381327320, 4.9), ...]

Each of the *_series() methods returns a list of tuples, each tuple being a couple in the form: (timestamp, measured value). When in the series values are not provided by the OWM Weather API, the numeric value is None. These convenience methods are especially useful if you need to chart the historic time series of the measured physical entities.

You can also get minimum, maximum and average values of each series:

# Get the minimum temperature value in the series
>>> his.min_temperature(unit="celsius")
(1381327200, 20.25)

# Get the maximum rain value in the series
>>> his.max_rain()
()

# Get the average wind value in the series
>>> his.average_wind()
4.816

Dumping objects’ content to JSON and XML

The PyOWM object instances can be dumped to JSON or XML strings:

# Dump a Weather object to JSON...
>>> w.to_JSON()
{'referenceTime':1377851530,'Location':{'name':'Palermo',
'coordinates':{'lon':13.35976,'lat':38.115822}'ID':2523920},...}

#... and to XML
>>> w.to_XML()
<?xml version='1.0' encoding='utf8'?>
<weather xmlns:w="http://github.com/csparpa/pyowm/tree/master/pyowm/weatherapi25/xsd/weather.xsd">
<w:status>Clouds</w:status>[...]</weather>

When you dump to XML you can decide wether or not to print the standard XML encoding declaration line and XML Name Schema prefixes using the relative switches:

>>> w.to_XML(xml_declaration=True, xmlns=False)

Checking if OWM Weather API is online

You can check out the OWM Weather API service availability:

>>> owm.is_API_online()
True

Printing objects

Most of PyOWM objects can be pretty-printed for a quick introspection:

>>> print w
<pyowm.weatherapi25.weather.Weather - reference time=2013-12-18 16:41:00, status=Drizzle>
>>> print w.get_location()
<pyowm.weatherapi25.location.Location - ID=1234, name=Barcelona, lon=2.9, lat=41.23>d