Reputation: 13
Bear with me if this is too simple, I'm just starting to learn to code.
Task:
Create a weather report from an API call. Ask for city, look up the city from web page and return the weather forecast for the next five days. Then ask for a city again, continue until CTRL-C is hit.
Build on, if asked for a city name that doesn't exit, ask for a city again.
City?
> fhusi
City not found
City?
> London
Here is the weather in London
2021-01-22: Heavy Cloud 6.2°C
2021-01-23: Heavy Cloud 3.8°C
2021-01-24: Heavy Rain 3.5°C
2021-01-25: Light Rain 3.8°C
2021-01-26: Showers 4.5°C
Traceback (most recent call last):
File "weather.py", line 45, in <module>
main()
File "weather.py", line 32, in main
city = search_city(query)
File "weather.py", line 19, in search_city
return seach_response[0]
IndexError: list index out of range
Here is my code: And yes, there is a lot of comments in it, that's how I remember my errors
# pylint: disable=missing-docstring
import sys
import urllib.parse
import requests
BASE_URI = "https://www.metaweather.com"
def search_city(query):
# : Look for a given city and disambiguate between several candidates. Return one city (or None)
seach_response = requests.get("https://www.metaweather.com/api/location/search/?query="+query).json() # [0] return results as dict format
# print(requests.get("https://www.metaweather.com/api/location/search/?query="+query).json)
# print(seach_response.status_code) --> remember to remove .json() from seach to see status code
# if seach_response.status_code != 200: --> didn't work, as a empty list is returned if city doesn't exit and not an error code
if seach_response == []:
print("City not found")
main()
return seach_response[0]
def weather_forecast(woeid):
# : Return a 5-element list of weather forecast for a given woeid
weather_response = requests.get(f'https://www.metaweather.com/api/location/{woeid}/').json()
#print(weather_response) --use https://jsonformatter.curiousconcept.com/# to see the data nicely and pick relevant data
weather = weather_response['consolidated_weather'][:5]
return weather
def main():
query = input("City?\n> ")
city = search_city(query)
#print(city) --control of code
woeid = city['woeid']
forecast = weather_forecast(woeid)
# : Display weather forecast for a given city
print(f"Here is the weather in {city['title']}")
for predition in forecast:
print(f"{predition['applicable_date']}: {predition['weather_state_name']} {round(predition['the_temp'],1)}\N{DEGREE SIGN}C")
if __name__ == '__main__':
try:
while True:
main()
except KeyboardInterrupt:
print('\nGoodbye!')
sys.exit(0)
Upvotes: 1
Views: 166
Reputation: 1154
The problem is at your search_city(query)
function. Take a look at the following lines.
if seach_response == []: # empty list
print("City not found")
main() # Execute main again
# Opps, main has executed and the function is still going
# but searc_response is an empty list so search_response[0] is going to be out of bounds
return seach_response[0]
To fix the above you need to return main()
instead of main()
. After this in main
you should check if search_city(query)
returned None.
So your code should look like this
def search_city(query):
seach_response = requests.get("https://www.metaweather.com/api/location/search/?query="+query).json() # [0] return results as dict format
if seach_response == []:
print("City not found")
return main() # return
return seach_response[0]
and also
def main():
query = input("City?\n> ")
city = search_city(query)
if city is None:
return
woeid = city['woeid'] # here if city is None it will throw an exception
forecast = weather_forecast(woeid)
print(f"Here is the weather in {city['title']}")
for predition in forecast:
print(f"{predition['applicable_date']}: {predition['weather_state_name']} {round(predition['the_temp'],1)}\N{DEGREE SIGN}C")
Upvotes: 1