I am trying to write a function that checks if the given variable is country name, city name, or some rubbish word. first I check if the variable is the country name. for that, I use an API. If the variable is not in the list of the country names I want to check it in the cities name list. The problem is that if the variable name does not exist it return a key error : 0 error and I cannot move to pass that and insert my city name checking code. Is there any way to get around this? This is what I have tired
def searchCountry():
try:
address = 'berlin'
checkcountry = 'https://restcountries.com/v3.1/name/' address
json_data = requests.get(checkcountry).json()
new_address = json_data[0]['name']['common']
except KeyError as e:
try:
if e == 0:
checkcities = 'https://countriesnow.space/api/v0.1/countries'
json_data = requests.get(checkcities).json()
cities_list = []
for i in range(0,len(json_data['data'])):
list = json_data['data'][i]['cities']
cities_list.append(list)
new_list=sum(cities_list, [])
for item in new_list:
if address == item:
return address
else:
print('error')
except:
pass
CodePudding user response:
While it's not guaranteed from other types reusing it, dict
generated KeyError
s pass the missing key as the sole argument to the constructor for KeyError
, and like all exceptions, it stores its arguments as a tuple
in the .args
attribute. So all you need to do is replace:
if e == 0:
with:
if e.args[0] == 0:
# Or to be absolutely sure it wasn't constructed with additional arguments:
if e.args == (0,): # Trailing comma mandatory to make it an actual one-tuple
CodePudding user response:
There is a bunch of cleanup we can do to guard against ever running into the key error using get()
. While we are at it, let's also query the country/city API once and get all the data and cache it so that repeated requests are faster.
This technique is often called a closure.
import requests
## -------------------------------
## Use a closure to fetch and cache coutry/city data
## -------------------------------
def build_country_searcher():
checkcities = 'https://countriesnow.space/api/v0.1/countries'
response = requests.get(checkcities)
if not response.ok:
raise Exception("failed to fetch data")
## -------------------------------
## Construct lookups for counties and cities once and cache results
## -------------------------------
countries = set()
city_to_country = {}
for country in response.json().get("data", []):
country_name = country["country"]
countries.add(country_name)
for city in country["cities"]:
city_to_country.setdefault(city, []).append(country_name)
## -------------------------------
## -------------------------------
## hidden utility function to just look up if the given name
## is a country. Note, we could also have used the abo
## -------------------------------
def check_country(name):
return name if name in countries else None
## -------------------------------
## -------------------------------
## Note that a city could be found in many countries so for
## fun, let's return those counties as a comma separated list.
## -------------------------------
def check_city(name):
return ", ".join(city_to_country.get(name, []))
## -------------------------------
## -------------------------------
## return our function that will process the lookups.
## -------------------------------
return lambda name: check_country(name) or check_city(name) or None
## -------------------------------
## -------------------------------
## -------------------------------
## Build out search function
## -------------------------------
country_searcher = build_country_searcher()
## -------------------------------
print(country_searcher("Germany"))
print(country_searcher("Berlin"))
print(country_searcher("Middle Earth"))
This should give you back:
Germany
Germany, United States
None