Source code for weatherapi

import requests
import multiprocessing
import queue

IP_INFO = 'http://ipinfo.io/json'
API_KEY = 'c67a801854866dfb'
API_ADDRESS = 'http://api.wunderground.com/api/'
API_CONDITIONS = '/conditions/q/'
TEMPERATURE_SCALE = 'c'


[docs]class WeatherApiWrapper: """Wunderground api wrapper for performing asynchronous requests. WeatherApiWrapper uses multiprocessing module to handle asynchronous wunderground api requests. Request can be started by calling call_weather_api() and response converted to json file can be collected with get_weather(). Only one request can be processed at the same time for each instance of WeatherApiWrapper. """ def __init__(self): self._input_queue = multiprocessing.Queue(maxsize=1) self._output_queue = multiprocessing.Queue(maxsize=1) self._api_call_process = multiprocessing.Process(target=weather_api_request, daemon=True, args=(self._input_queue, self._output_queue,))
[docs] def call_weather_api(self, country, region): """Starts asynchronous api request. Only one request can be processed at the same time for each instance of WeatherApiWrapper. To obtain results get_weather() has to be called. Args: country: country of interest. Either abbreviation or full english name. region: region of interest e.g city/province. Returns: 0 if weather api request was successfully made or 1 if api request is already processing. Raises: ValueError: If impossible behaviour occurred. """ if not self._api_call_process.is_alive(): try: # Request process is not running so we put arguments # into the input queue. self._input_queue.put((country, region), block=False) except queue.Full: raise ValueError("Input queue was full. This should never happen.") try: self._api_call_process.start() except AssertionError: # This exception means that our process was already # started and finished execution so we join it and # then create and start a new one. self._api_call_process.join() self._api_call_process = multiprocessing.Process(target=weather_api_request, daemon=True, args=(self._input_queue, self._output_queue,)) self._api_call_process.start() return 0 return 1
[docs] def get_weather(self): """Return request results and according return code. Returns: returncode: -1 if no request was made with call_weather_api function, 0 if weather information was successfully returned or 1 if api request is still being processed. weather_json: json file containing weather information for requested region or None (see returncode = -1 or 1). """ weather_json = None if self._api_call_process.is_alive(): returncode = 1 else: try: weather_json = self._output_queue.get(block=False) self._api_call_process.join() returncode = 0 except queue.Empty: returncode = -1 return returncode, weather_json
[docs]def weather_api_request(input_queue, output_queue): """Callback function performing weather information requests. Args: input_queue: queue for passing city and region arguments for api request. These arguments should be passed in one tuple. output_queue: queue for passing request results. Raises: ValueError: if no arguments were passed through the input queue. """ try: location = input_queue.get(block=True, timeout=1) country = location[0] region = location[1] except queue.Empty: raise ValueError('Input queue empty.') response = requests.get(API_ADDRESS + API_KEY + API_CONDITIONS + country + '/' + region + '.json') weather_json = response.json() try: output_queue.put(weather_json, block=False) except queue.Full: # This exception will occur if previous request's results were # not collected with get_weather(). Replacing old results with # new. output_queue.get(block=True, timeout=1) output_queue.put(weather_json, block=False)