Lab - Integrate A REST API in A Python Application: Objectives
Lab - Integrate A REST API in A Python Application: Objectives
Objectives
Part 1: Launch the DEVASC VM
Part 2: Demonstrate the MapQuest Directions
Application Part 3: Get a MapQuest API Key
Part 4: Build the Basic MapQuest Direction Application
Part 5: Upgrade the MapQuest Directions Application with More
Features Part 6: Test Full Application Functionality
Background / Scenario
In this lab, you will create an application in Visual Studio Code (VS Code) that retrieves JSON data from the
MapQuest Directions API, parses the data, and formats it for output to the user. You will use the GET Route request
from the MapQuest Directions API. Review the GET Route Directions API documentation here:
https://developer.mapquest.com/documentation/directions-api/route/get/
Note: If the above link no longer works, search for “MapQuest API Documentation”.
Required Resources
1 PC with operating system of your choice
Virtual Box or VMWare
DEVASC Virtual Machine
Instructions
2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public Page 1 of 16 www.netacad.com
Lab - Integrate a REST API in a Python Application
Note: To see the JSON for the above output, you can copy the URL in a browser tab. However, you will need to replace
your_api_key with the MapQuest API key you obtain in Part 3.
2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public Page 2 of 16 www.netacad.com
d. Select File > New File.
e. Select File > Save as… and name the file mapquest_parse-json_1.py and click Save.
Step 3: Build the URL for the request to the MapQuest directions API.
The first step in creating your API request is to construct the URL that your application will use to make the call.
Initially, the URL will be the combination of the following variables:
main_api - the main URL that you are accessing
orig - the parameter to specify your point of origin
dest - the parameter to specify your destination
key - the MapQuest API key you retrieved from the developer website
a. Create variables to build the URL that will be sent in the request. In the following code, replace
your_api_key with the Consumer Key you copied from your MapQuest developer account.
main_api = "https://www.mapquestapi.com/directions/v2/route?"
orig = "Washington, D.C."
dest = "Baltimore, Md"
key = "your_api_key"
b. Combine the four variables main_api, orig, dest, and key to format the requested URL. Use the urlencode
method to properly format the address value. This function builds the parameters part of the URL and converts
possible special characters in the address value into acceptable characters (e.g. space into “+” and a comma into
“%2C”).
url = main_api + urllib.parse.urlencode({"key":key, "from":orig, "to":dest})
c. Create a variable to hold the reply of the requested URL and print the returned JSON data. The json_data variable
holds a Python’s Dictionary representation of the json reply of the get method of the requests module. The
requests.get will make the API call to the MapQuest API. The print statement will be used temporarily to check
the returned data. You will replace this print statement with more sophisticated display options later in the lab.
json_data = requests.get(url).json()
print(json_data)
d. Your final code should look like this, but with a different value for the key.
import urllib.parse
import requests
main_api = "https://www.mapquestapi.com/directions/v2/route?"
orig = "Washington, D.C."
dest = "Baltimore, Md"
key = "fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ" #Replace with your MapQuest key
json_data = requests.get(url).json()
print(json_data)
c. Change the orig and dest variables. Rerun the script to get different results. To ensure the results you want, it is
best to include both the city and the state for cities in the USA. When referring to cities in other countries, you can
usually use either the English name for the city and country or the native name. For example:
orig = "Rome, Italy"
dest = "Frascati, Italy"
or
orig = "Roma, Italia"
dest = "Frascati, Italia"
Step 5: Print the URL and check the status of the JSON request.
Now that you know the JSON request is working, you can add some more functionality to the application.
a. Save your script as mapquest_parse-json_2.py.
b. Delete the print(json_data) statement as you no longer need to test that the request is properly
formatted.
c. Add the statements below, which will do the following:
o Print the constructed URL so that the user can see the exact request made by the application.
o Parse the JSON data to obtain the statuscode value.
o Start an if loop that checks for a successful call, which is indicated by a returned value of 0. Add a print
statement to display the statuscode value and its meaning. The \n adds a blank line below the output.
Later in this lab, you will add elif and else statements for different statuscode values.
print("URL: " + (url))
json_data = requests.get(url).json()
json_status = json_data["info"]["statuscode"]
if json_status == 0:
print("API Status: " + str(json_status) + " = A successful route call.\n")
b. Save and run your mapquest_parse-json_2.py script and verify it works. Troubleshoot your code, if
necessary. You should get output similar to the following. Notice your key is embedded in the URL request.
devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_2.py
URL:
https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f
rom=Washington%2C+D.C.&to=Baltimore%2C+Md
API Status: 0 = A successful route call.
devasc@labvm:~/labs/devnet-src/mapquest$
main_api = "https://www.mapquestapi.com/directions/v2/route?"
key = "fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ"
while True:
orig = input("Starting Location: ")
dest = input("Destination: ")
url = main_api + urllib.parse.urlencode({"key": key, "from":orig, "to":dest})
print("URL: " + (url))
json_data = requests.get(url).json()
json_status = json_data["info"]["statuscode"]
if json_status == 0:
print("API Status: " + str(json_status) + " = A successful route call.\n")
devasc@labvm:~/labs/devnet-src/mapquest$
d. Expand the route dictionary (click on the plus sign "+" before route) and investigate the rich data. There are
values to indicate whether the route has toll roads, bridges, tunnels, highways, closures, or crosses into other
countries. You should also see values for distance, the total time the trip will take, and fuel usage. To parse and
display this data in your application, you would specify the route dictionary and then select key/value pair you
want to print. You will do some parsing of the route dictionary in the next part of the lab.
Step 1: Display trip summary information to include duration, distance, and fuel used.
a. Save your script as mapquest_parse-json_5.py.
b. Below the API status print command, add several print statements that display the from and to locations, as well
as the formattedTime, distance, and fuelUsed keys.
The additional statements also include print statements that will display a double line before the next request for a
starting location. Make sure these statements are embedded in the while True function.
if json_status == 0:
print("API Status: " + str(json_status) + " = A successful route call.\n")
print("=============================================")
print("Directions from " + (orig) + " to " + (dest))
print("Trip Duration: " + (json_data["route"]["formattedTime"]))
print("Miles: " + str(json_data["route"]["distance"]))
print("Fuel Used (Gal): " + str(json_data["route"]["fuelUsed"]))
print("=============================================")
=============================================
Directions from Washington, D.C. to Baltimore, Md
Trip Duration: 00:49:29
Miles: 38.089
Fuel Used (Gal): 1.65
=============================================
Starting Location: q
devasc@labvm:~/labs/devnet-src/mapquest$
d. By defauilt, MapQuest uses the imperial system and there is not a request parameter to change data to the metric
system. Therefore, you should probably convert your application to display metric values, as shown below.
print("Kilometers: " + str((json_data["route"]["distance"])*1.61))
print("Fuel Used (Ltr): " + str((json_data["route"]["fuelUsed"])*3.78))
e. Run the modified mapquest_parse-json_5.py script to see the following output:
devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_5.py
Starting Location: Washington, D.C.
Destination: Baltimore, Md
URL:
https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f
rom=Washington%2C+D.C.&to=Baltimore%2C+Md
API Status: 0 = A successful route call.
=============================================
Directions from Washington, D.C. to Baltimore, Md
Trip Duration: 00:49:29
Kilometers: 61.32329
Fuel Used (Ltr): 6.236999999999999
=============================================
Starting Location: q
devasc@labvm:~/labs/devnet-src/mapquest$
f. The extra decimal places for Kilometers and Fuel Used are not helpful. Use the "{:.2f}".format argument to
format the float values to 2 decimal places before converting them to string values, as shown below. Each
statement should be on one line.
print("Kilometers: " +
str("{:.2f}".format((json_data["route"]["distance"])*1.61)))
print("Fuel Used (Ltr): " +
str("{:.2f}".format((json_data["route"]["fuelUsed"])*3.78)))
c. Expand the first dictionary in the maneuvers list. Each dictionary contains a narrative key with a value, such as
“Start out going north...”, as shown below. You need to parse the JSON data to extract the value for the narrative
key to display inside your application.
- legs: [
- {
hasTollRoad: false,
hasBridge: true,
destNarrative: "Proceed to BALTIMORE, MD.",
distance: 38.089,
hasTimedRestriction: false,
hasTunnel: false,
hasHighway: true,
index: 0,
formattedTime: "00:49:29",
origIndex: -1,
hasAccessRestriction: false,
hasSeasonalClosure: false,
hasCountryCross: false,
- roadGradeStrategy: [
[ ]
],
destIndex: 3,
time: 2969,
hasUnpaved: false,
origNarrative: "",
- maneuvers: [
- {
distance: 0.792,
- streets: [
"6th St",
"US-50 E",
"US-1 N"
],
narrative: "Start out going north on 6th St/US-50E/US-1 N toward
Pennsylvania Ave/US-1 Alt N.",
turnType: 0,
- startPoint: {
lng: -77.019913,
lat: 38.892063
},
index: 0,
formattedTime: "00:02:06",
directionName: "North",
maneuverNotes: [ ],
linkIds: [ ],
- signs: [
- {
extraText: "",
ext: "50",
type: 2,
<output omitted>
Note: Word wrap was added for the value in the narrative for display purposes.
Step 4: Add a for loop to iterate through the maneuvers JSON data.
Complete the following steps to upgrade the application to display the value for the narrative key. You will do this by
creating a for loop to iterate through the maneuvers list, displaying the narrative value for each maneuver from starting
location to destination.
a. Save your script as mapquest_parse-json_6.py.
b. Add a for loop, highlighted below, after the second double line print statement. The for loop iterates through
each maneuvers list and does the following:
1) Prints the narrative value.
2) Converts miles to kilometers with *1.61.
3) Formats the kilometer value to print only two decimal places with the "{:.2f}".format function.
c. Add a print statement that will display a double line before the application asks for another starting
location, as shown below.
Note: The double line print statement is not indented within the for loop. It therefore is part of the previous
if statement that checks the statuscode parameter.
print("Fuel Used (Ltr): " + str("{:.2f}".format((json_data["route"]["fuelUsed"])*3.78)))
print("=============================================")
for each in json_data["route"]["legs"][0]["maneuvers"]:
print((each["narrative"]) + " (" + str("{:.2f}".format((each["distance"])*1.61) + " km)"))
print("=============================================\n")
=============================================
Directions from Washington, D.C. to Baltimore, Md
Trip Duration: 00:49:29
Kilometers: 61.32
Fuel Used (Ltr): 6.24
=============================================
Start out going north on 6th St/US-50 E/US-1 N toward Pennsylvania Ave/US-1 Alt N.
(1.28 km)
Turn right onto New York Ave/US-50 E. Continue to follow US-50 E (Crossing into
Maryland). (7.51 km)
Take the Balt-Wash Parkway exit on the left toward Baltimore. (0.88 km)
Merge onto MD-295 N. (50.38 km)
Turn right onto W Pratt St. (0.86 km)
Turn left onto S Calvert St/MD-2. (0.43 km)
Welcome to BALTIMORE, MD. (0.00 km)
=============================================
Starting Location: q
devasc@labvm:~/labs/devnet-src/mapquest$
if json_status == 0:
print("API Status: " + str(json_status) + " = A successful route call.\n")
But what happens if the statuscode is not equal to 0? For example, the user might enter an invalid location or might
not enter one or more locations. If so, then the application displays the URL and asks for a new starting location. The
user has no idea what happened.
a. To cause your application to fail without user notification, try the following values in your application. You should
see similar results.
devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_6.py
Starting Location: Washington, D.C.
Destination: Beijing, China
URL:
https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f
rom=Washington%2C+D.C.&to=Beijing%2C+China
Starting Location: Washington, D.C.
Destination: Bal
URL:
https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f
rom=Washington%2C+D.C.&to=Bal
Starting Location: q
devasc@labvm:~/labs/devnet-src/mapquest$
b. Copy one of the URLs to a Chromium browser tab. Notice that the only entry in route dictionary is a routeError
dictionary with the errorCode 2. In the info dictionary, the statuscode is 402. Therefore, your if loop never
executed the code for when the statuscode is 0.
c. Save your script as mapquest_parse-json_7.py.
d. To provide error information when statuscode is equal to 402, 611, or another value, add two elif statements
and an else statement to your if loop. Your elif and else statements must align with the previous if statement.
After the last double line print statement under the if json_status == 0, add the following elif and else
statements:
if json_status == 0:
<statements omitted>
for each in json_data["route"]["legs"][0]["maneuvers"]:
print((each["narrative"]) + " (" +
str("{:.2f}".format((each["distance"])*1.61) + " km)"))
print("=============================================\n")
elif json_status == 402:
print("**********************************************")
print("Status Code: " + str(json_status) + "; Invalid user inputs for one or both
locations.")
print("**********************************************\n")
elif json_status == 611:
print("**********************************************")
print("Status Code: " + str(json_status) + "; Missing an entry for one or both
locations.")
print("**********************************************\n")
else:
print("************************************************************************")
print("For Staus Code: " + str(json_status) + "; Refer to:")
print("https://developer.mapquest.com/documentation/directions-api/status-codes")
print("************************************************************************\n")
The first elif statement prints if the statuscode value is 402 for an invalid location. The second elif statement
prints if the statuscode value is 611 because the user did not provide an entry for one or both locations. The else
statement prints for all other statuscode values, such as when the MapQuest site returns an error. The else
statement ends the if/else loop and returns the application to the while loop.
=============================================
Directions from Washington, D.C. to Baltimore, Md
Trip Duration: 00:49:29
Kilometers: 61.32
Fuel Used (Ltr): 6.24
=============================================
Start out going north on 6th St/US-50 E/US-1 N toward Pennsylvania Ave/US-1 Alt N.
(1.28 km)
Turn right onto New York Ave/US-50 E. Continue to follow US-50 E (Crossing into
Maryland). (7.51 km)
Take the Balt-Wash Parkway exit on the left toward Baltimore. (0.88 km)
Merge onto MD-295 N. (50.38 km)
Turn right onto W Pratt St. (0.86 km)
Turn left onto S Calvert St/MD-2. (0.43 km)
Welcome to BALTIMORE, MD. (0.00 km)
=============================================
=============================================
Directions from Moscow, Russia to Beijing, China
Trip Duration: 84:31:10
Kilometers: 7826.83
Fuel Used (Ltr): 793.20
=============================================
Start out going west on Кремлёвская набережная/Kremlin Embankment. (0.37 km)
Turn slight right onto ramp. (0.15 km)
Turn slight right onto Боровицкая площадь. (0.23 km)
<output omitted>
Turn slight left onto 前门东大街/Qianmen East Street. (0.31 km)
Turn left onto 广场东侧路/E. Guangchang Rd. (0.82 km)
广场东侧路/E. Guangchang Rd becomes 东长安街/E. Chang'an Str. (0.19 km)
Welcome to BEIJING. (0.00 km)
=============================================