Server-Side Scripting/Internet Data/Python (Flask)

From Wikiversity
Jump to navigation Jump to search

app.py[edit | edit source]

# This program reads JSON data from Wikidata with countries
# and Celsius temperatures. It displays the data in Celsius
# and Fahrenheit sorted in decending order by temperature.
#
# References:
#   https://www.mathsisfun.com/temperature-conversion.html
#   https://en.wikibooks.org/wiki/Python_Programming
#   https://www.wikidata.org/wiki/Wikidata:SPARQL_query_service

import flask
import json
import urllib.parse
import urllib.request

app = flask.Flask(__name__)

URL = "https://query.wikidata.org/sparql"
QUERY = """
SELECT DISTINCT ?Country ?MaximumTemperature WHERE {
  ?countryItem wdt:P31 wd:Q6256;
    p:P6591 ?maximumTemperatureRecord.
  ?maximumTemperatureRecord psv:P6591 ?maximumTemperatureValue.
  ?maximumTemperatureValue wikibase:quantityAmount ?maximumTemperatureQuantity;
    wikibase:quantityUnit ?temperatureUnit.
  {
    ?countryItem rdfs:label ?Country.
    FILTER((LANG(?Country)) = "en")
  }
  {
    ?temperatureUnit wdt:P5061 ?unitSymbol.
    FILTER((LANG(?unitSymbol)) = "en")
    FILTER(CONTAINS(?unitSymbol, "C"))
  }
  BIND(CONCAT(STR(?maximumTemperatureQuantity), " ", ?unitSymbol) AS ?MaximumTemperature)
}
ORDER BY (?Country)
"""

@app.route('/', methods=["GET"])
def root_get():
    result = "<h1>Temperature Conversion</h1>"
    result += f"<h2>Wikidata</h2>"
    result += get_data()
    return result

def get_data():
    try:
        data = get_raw_data(URL, QUERY)
        records = get_records(data)
        records.sort(key=lambda x:x["celsius"], reverse=True)
        result = format_table(records)
        return result
    except Exception as exception:
        return str(exception)

def get_raw_data(url, query):
    url += "?query=" + urllib.parse.quote(query)
    url += "&format=json"
    data = urllib.request.urlopen(url).read().decode()
    data = json.loads(data)
    return data

def get_records(data):
    records = []
    for dictionary in data["results"]["bindings"]:
        record = get_record(dictionary)
        records.append(record)
    records.sort(key=lambda x:x["celsius"], reverse=True)
    return records 

def get_record(dictionary):
    country = dictionary["Country"]["value"]
    celsius = dictionary["MaximumTemperature"]["value"]

    index = celsius.find(" °C")
    if index < 0:
        raise ValueError("Invalid data format")

    try:
        celsius = float(celsius[0:index])
        fahrenheit = celsius * 9 / 5 + 32
    except:
        raise ValueError("Invalid temperature data")

    record = {}
    record["country"] = country
    record["celsius"] = celsius
    record["fahrenheit"] = fahrenheit
    return record

def format_table(records):
    result = "<table><tr><th>Country</th>"
    result += "<th>Celsius</th>"
    result += "<th>Fahrenheit</th></tr>"

    for record in records:
        result += f"<tr><td>{record['country']}</td>" 
        result += f"<td>{record['celsius']:.1f}° C</td>"
        result += f"<td>{record['fahrenheit']:.1f}° F</td></tr>"

    result += "</table>"
    return result

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)

Try It[edit | edit source]

Copy and paste the code above into the following free online development environment or use your own Python (Flask) compiler / interpreter / IDE.

See Also[edit | edit source]