Files
troupe-standup/wizard-work/ledger/extract_countries.py
T

101 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""Flatten the REST Countries v3.1 dataset into a clean, flat table.
Usage:
python3 extract_countries.py <source_json> <output_csv>
Source (raw, from the REST Countries repository):
https://raw.githubusercontent.com/restcountries/restcountries/master/src/main/resources/countriesV3.1.json
The JSON is an array of 250 country records; this script flattens every record
to one CSV row with the fixed 14-column contract below.
Columns (order):
name_common | name_official | alpha2 | alpha3 | numeric |
region | subregion | capital | population | area_km2 |
currencies | languages | tlds | flag
"""
import csv
import json
import sys
def as_text(value):
"""Empty string for None/empty, plain str otherwise."""
if value is None or value == '':
return ''
return str(value)
def list_join(value):
"""Join a list of strings with ' | '; empty string for None."""
if value is None:
return ''
return ' | '.join(str(item) for item in value)
def currency_codes(currencies):
if not isinstance(currencies, dict):
return ''
return ' | '.join(sorted(currencies.keys()))
def language_codes(languages):
if not isinstance(languages, dict):
return ''
return ' | '.join(sorted(languages.keys()))
def flatten(record):
name = record.get('name') or {}
return [
as_text(name.get('common')), # name_common
as_text(name.get('official')), # name_official
as_text(record.get('cca2')), # alpha2
as_text(record.get('cca3')), # alpha3
as_text(record.get('ccn3')), # numeric
as_text(record.get('region')), # region
as_text(record.get('subregion')), # subregion
list_join(record.get('capital')), # capital
as_text(record.get('population')), # population
as_text(record.get('area')), # area_km2
currency_codes(record.get('currencies')), # currencies
language_codes(record.get('languages')), # languages
list_join(record.get('tld')), # tlds
as_text(record.get('flag')), # flag
]
HEADERS = [
'name_common', 'name_official', 'alpha2', 'alpha3', 'numeric',
'region', 'subregion', 'capital', 'population', 'area_km2',
'currencies', 'languages', 'tlds', 'flag',
]
def main():
if len(sys.argv) != 3:
sys.stderr.write('usage: extract_countries.py <source_json> <output_csv>\n')
return 2
source_path, out_path = sys.argv[1], sys.argv[2]
try:
with open(source_path, encoding='utf-8') as fh:
records = json.load(fh)
except (OSError, ValueError) as exc:
sys.stderr.write('cannot read source %s: %s\n' % (source_path, exc))
return 1
if not isinstance(records, list):
sys.stderr.write('source JSON is not a list\n')
return 1
with open(out_path, 'w', encoding='utf-8', newline='') as fh:
writer = csv.writer(fh, lineterminator='\n')
writer.writerow(HEADERS)
for record in records:
writer.writerow(flatten(record))
print('records_in: %d' % len(records))
print('wrote: %s' % out_path)
return 0
if __name__ == '__main__':
sys.exit(main())