Last Updated on May 2, 2021
When using the AWS Price List API, one of the most used attribute is the location
attribute. This attribute is used to filter the region of your target resource.
Unfortunately, the location
attribute is not in the region code that we use when programming in Python and Boto3, like us-east-1. Instead, it is descriptive like US East (N. Virginia). This is not readily available in Boto3 client or resource.
Below is the python function get_region_name
, this converts the region code, eu-west-2, to the region name that AWS Price List API attribute location
will accept, EU (London).
import json
from pkg_resources import resource_filename
def get_region_name(region_code):
endpoint_file = resource_filename('botocore', 'data/endpoints.json')
with open(endpoint_file, 'r') as f:
endpoint_data = json.load(f)
region_name = endpoint_data['partitions'][0]['regions'][region_code]['description']
region_name = region_name.replace('Europe', 'EU')
return region_name
if __name__ == "__main__":
region_code = 'ap-south-1'
region_name = get_region_name(region_code)
print(region_name)
region_code = 'eu-west-2'
region_name = get_region_name(region_code)
print(region_name)
region_code = 'us-east-2'
region_name = get_region_name(region_code)
print(region_name)
Output
Asia Pacific (Mumbai)
EU (London)
US East (Ohio)
Code Explained
We first take the filepath of the endpoints.json inside the botocore library.
endpoint_file = resource_filename('botocore', 'data/endpoints.json')
Since boto3 is built atop of the botocore library, when we install boto3 it will automatically install botocore.
Then we access the contents of the endpoints.json file, convert it to dictionary using json.load
and store to the endpoint_data
variable.
with open(endpoint_file, 'r') as f:
endpoint_data = json.load(f)
Then get the region name from the dictionary and return it.
region_name = endpoint_data['partitions'][0]['regions'][region_code]['description']
We need to modify all Europe Regions since the location
attribute does not support values with Europe
, it support EU
instead.
region_name = region_name.replace('Europe', 'EU')
Then return the region_name
.
return region_name
Getting the Region Names of All Regions
If you want to list all the active region codes and region names in the AWS Account, then change the main part of the code to this.
if __name__ == "__main__":
import boto3
ec2_client = boto3.client('ec2')
response = ec2_client.describe_regions(AllRegions=True)
regions = response['Regions']
for region in regions:
region_code = region['RegionName']
region_name = get_region_name(region_code)
print(region_code, '\t', region_name)
Output
af-south-1 Africa (Cape Town)
eu-north-1 EU (Stockholm)
ap-south-1 Asia Pacific (Mumbai)
eu-west-3 EU (Paris)
eu-west-2 EU (London)
eu-south-1 EU (Milan)
eu-west-1 EU (Ireland)
ap-northeast-3 Asia Pacific (Osaka)
ap-northeast-2 Asia Pacific (Seoul)
me-south-1 Middle East (Bahrain)
ap-northeast-1 Asia Pacific (Tokyo)
sa-east-1 South America (Sao Paulo)
ca-central-1 Canada (Central)
ap-east-1 Asia Pacific (Hong Kong)
ap-southeast-1 Asia Pacific (Singapore)
ap-southeast-2 Asia Pacific (Sydney)
eu-central-1 EU (Frankfurt)
us-east-1 US East (N. Virginia)
us-east-2 US East (Ohio)
us-west-1 US West (N. California)
us-west-2 US West (Oregon)
Efficient access to Region Names multiple times
If your program will be accessing the different region names multiple times then I suggest creating a dictionary where the key is the region code and the values is the region name. This implementation will be faster.
See get_region_code_name_dict
function below for this implementation.
import json
from pkg_resources import resource_filename
def get_region_code_name_dict():
endpoint_file = resource_filename('botocore', 'data/endpoints.json')
with open(endpoint_file, 'r') as f:
endpoint_data = json.load(f)
regions = endpoint_data['partitions'][0]['regions']
region_code_name_dict = {}
for region_code in regions.keys():
region_name = regions[region_code]['description']
region_code_name_dict[region_code] = region_name.replace('Europe', 'EU')
return region_code_name_dict
if __name__ == "__main__":
# regions_code_name_dict is a dictionary that has the region_code as the key and the region_name as the value
regions_code_name_dict = get_region_code_name_dict()
region_code = 'us-east-1'
region_name = regions_code_name_dict[region_code]
print(region_name)
region_code = 'ap-southeast-2'
region_name = regions_code_name_dict[region_code]
print(region_name)
region_code = 'eu-central-1'
region_name = regions_code_name_dict[region_code]
print(region_name)
Output
US East (N. Virginia)
Asia Pacific (Sydney)
EU (Frankfurt)
If we do print(region_code_name_dict)
it will look like this. (Manually formatted for easier reading)
{
'af-south-1': 'Africa (Cape Town)',
'ap-east-1': 'Asia Pacific (Hong Kong)',
'ap-northeast-1': 'Asia Pacific (Tokyo)',
'ap-northeast-2': 'Asia Pacific (Seoul)',
'ap-northeast-3': 'Asia Pacific (Osaka)',
'ap-south-1': 'Asia Pacific (Mumbai)',
'ap-southeast-1': 'Asia Pacific (Singapore)',
'ap-southeast-2': 'Asia Pacific (Sydney)',
'ca-central-1': 'Canada (Central)',
'eu-central-1': 'EU (Frankfurt)',
'eu-north-1': 'EU (Stockholm)',
'eu-south-1': 'EU (Milan)',
'eu-west-1': 'EU (Ireland)',
'eu-west-2': 'EU (London)',
'eu-west-3': 'EU (Paris)',
'me-south-1': 'Middle East (Bahrain)',
'sa-east-1': 'South America (Sao Paulo)',
'us-east-1': 'US East (N. Virginia)',
'us-east-2': 'US East (Ohio)',
'us-west-1': 'US West (N. California)',
'us-west-2': 'US West (Oregon)'
}
Lambda Functions delay in boto3 updates
When Asia Pacific (Osaka) or ap-northeast-3 was recently launched, the get_region_name
was throwing a KeyError: ap-northeast-3
. When we investigated, it turns out that the boto3 and botocore was not yet updated during development.
To solve this, either upload the updated package of boto3 and botocore to the Lambda Function or use a try/except block that would handle the new region_code
just like the code below.
import json
from pkg_resources import resource_filename
def get_region_name(region_code):
endpoint_file = resource_filename('botocore', 'data/endpoints.json')
with open(endpoint_file, 'r') as f:
endpoint_data = json.load(f)
try:
region_name = endpoint_data['partitions'][0]['regions'][region_code]['description']
region_name = region_name.replace('Europe', 'EU')
except Exception as e:
if region_code == 'ap-northeast-3':
return 'Asia Pacific (Osaka)'
raise e # Raise an exception when the region_code cannot be found
return region_name
if __name__ == "__main__":
region_name = get_region_name('ap-northeast-3')
print(region_name)
The best method is to actually use an updated local boto3 package in Lambda, but if you are the type that tries to avoid uploading a python package then the code above would help.
KeyError on non-Lambda Python Environment
If you are developing not for Lambda Functions, like a development, staging or production environment running locally or on services, check the latest endpoints.json of botocore in the master branch of their github repository.
If there is an entry of the region code that raises an exception, then an update to your boto3 package will do the trick.
To update boto3, just run the command below.
pip3 install boto3 --upgrade
I hope the above helps in getting the Region Name that you need for the Boto3 AWS Price List API.