329

I have a boto3 client :

boto3.client('kms')

But it happens on new machines, They open and close dynamically.

    if endpoint is None:
        if region_name is None:
            # Raise a more specific error message that will give
            # better guidance to the user what needs to happen.
            raise NoRegionError()

Why is this happening? and why only part of the time?

Rot-man
  • 18,045
  • 12
  • 118
  • 124
WebQube
  • 8,510
  • 12
  • 51
  • 93
  • 2
    Because boto3 client can't find AWS profile from set of default credentials method : http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html. – mootmoot Nov 02 '16 at 11:26

13 Answers13

645

One way or another you must tell boto3 in which region you wish the kms client to be created. This could be done explicitly using the region_name parameter as in:

kms = boto3.client('kms', region_name='us-west-2')

or you can have a default region associated with your profile in your ~/.aws/config file as in:

[default]
region=us-west-2

or you can use an environment variable as in:

export AWS_DEFAULT_REGION=us-west-2

but you do need to tell boto3 which region to use.

PythonJin
  • 4,034
  • 4
  • 32
  • 40
garnaat
  • 44,310
  • 7
  • 123
  • 103
  • 2
    How do I know myself which region to use? – tadasajon Mar 31 '17 at 17:05
  • 1
    If you are trying to access existing resources choose the region in which those resources exist. If you are going to create new resources, most people choose a region which is closest to them geographically for faster response times. Not all regions support the same set of services so if you need a particular service make sure you choose a region that supports it. – garnaat Apr 01 '17 at 18:18
  • I guess my question is: how do I know which region I have already chosen? I suppose it must be in the AWS UI somewhere... – tadasajon Apr 03 '17 at 14:13
  • 1
    To find out which regions provide which services: Amazon Web Services Region Table https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/ – Nic May 23 '17 at 04:53
  • 3
    do you know why "export AWS_DEFAULT_REGION=us-west-2" or ~/.aws/config file not working – fatih tekin Nov 28 '17 at 20:44
  • I was looking for this answer in regard to SNS. Worked as well. – Strabek Nov 15 '18 at 11:58
  • 1
    works as well with `boto3.resource('service_name', region_name='us-west-2')` – openwonk Aug 13 '19 at 00:21
  • 20
    I wish boto3 could just use the region of the ec2 instance that's running the code. – Selçuk Cihan Feb 06 '20 at 09:26
  • 1
    Yeah I have my AWS_DEFAULT_REGION set and still no workey – ThisGuyCantEven Feb 25 '20 at 15:53
  • Why is it not finding my creds even though I input them exactly as they should be? – Blairg23 Apr 07 '20 at 19:41
  • 1
    Setting a default region in ./aws/config did not solve the issue for me. I had to edit the file directly, adding region name parameter: `boto3.client('elbv2')` to `boto3.client('elbv2', region_name='us-east-1')` – user1653042 Jul 01 '21 at 15:59
  • @SelçukCihan I agree but you could also do that relatively easily: https://stackoverflow.com/a/73442662/9792594 – Alex L Aug 22 '22 at 09:09
32
os.environ['AWS_DEFAULT_REGION'] = 'your_region_name'

In my case sensitivity mattered.

Marcello B.
  • 4,177
  • 11
  • 45
  • 65
Anthony G
  • 329
  • 3
  • 2
15

you can also set environment variables in the script itself, rather than passing region_name parameter

os.environ['AWS_DEFAULT_REGION'] = 'your_region_name'

case sensitivity may matter.

Ben Watson
  • 5,357
  • 4
  • 42
  • 65
Abhishek Garg
  • 326
  • 2
  • 7
11

For Python 2 I have found that the boto3 library does not source the region from the ~/.aws/config if the region is defined in a different profile to default. So you have to define it in the session creation.

session = boto3.Session(
    profile_name='NotDefault',
    region_name='ap-southeast-2'
)

print(session.available_profiles)

client = session.client(
    'ec2'
)

Where my ~/.aws/config file looks like this:

[default]
region=ap-southeast-2

[NotDefault]
region=ap-southeast-2

I do this because I use different profiles for different logins to AWS, Personal and Work.

RalfFriedl
  • 1,134
  • 3
  • 11
  • 12
David Edson
  • 156
  • 1
  • 5
8

If you are using lambdas, then you would likely want to use the region the lambda is deployed in. You can use the following

import boto3
import json
import os

def lambda_handler(event, context):
    region = os.environ['AWS_REGION']
    print('Lambda region: ', region)
    kms = boto3.client('kms', region_name=region)
VenVig
  • 645
  • 1
  • 10
  • 14
7

regions = [
            'eu-north-1', 'ap-south-1', 'eu-west-3', 'eu-west-2',
            'eu-west-1', 'ap-northeast-3', 'ap-northeast-2'
            'ap-northeast-1', 'sa-east-1', 'ca-central-1', 
            'ap-southeast-2', 'eu-central-1', 'us-east-1', 'us-east-2',
            'us-west-1', 'us-west-2']
for r in regions:
   kms = boto3.client('kms', region_name= r)
Harshal
  • 199
  • 3
  • 8
5

Alternatively you can run the following (aws cli)

aws configure --profile $PROFILE_NAME

it'll prompt you for the region.

notice in ~/.aws/config it's:

[default]
region = ap-southeast-1
output = json

[profile prod]
region = ap-southeast-1
output = json

[profile profile name] in the square brackets

altimit
  • 421
  • 5
  • 11
4

I believe, by default, boto picks the region which is set in aws cli. You can run command #aws configure and press enter (it shows what creds you have set in aws cli with region)twice to confirm your region.

3

For those using CloudFormation template. You can set AWS_DEFAULT_REGION environment variable using UserData and AWS::Region. For example,

MyInstance1:
    Type: AWS::EC2::Instance                
    Properties:                           
        ImageId: ami-04b9e92b5572fa0d1 #ubuntu
        InstanceType: t2.micro
        UserData: 
            Fn::Base64: !Sub |
                    #!/bin/bash -x

                    echo "export AWS_DEFAULT_REGION=${AWS::Region}" >> /etc/profile
Marcin
  • 215,873
  • 14
  • 235
  • 294
3

you could always set it to the same region that the EC2 is in if you like. This is with bash but you could easily reproduce this in python:

EC2_AVAIL_ZONE=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
EC2_REGION="`echo $EC2_AVAIL_ZONE | sed -e 's:\([0-9][0-9]*\)[a-z]*\$:\\1:'`"
# if unset, set it:
export AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-$EC2_REGION}"

python:

import os
import re
from subprocess import check_output

EC2_AVAIL_ZONE = check_output(["curl", "-s", "http://169.254.169.254/latest/meta-data/placement/availability-zone"]).decode().strip()
EC2_REGION = re.sub(r"^(\w{2}-\w{3,10}-[0-9][0-9]*)[a-z]*$", r"\1", EC2_AVAIL_ZONE)
# if unset, set it:
os.environ["AWS_DEFAULT_REGION"] = os.getenv("AWS_DEFAULT_REGION", EC2_REGION)
Alex L
  • 4,168
  • 1
  • 9
  • 24
1

We have the configured regions stored in our ~/.aws/config file. Here is a pure python way of reading the correct region from this file based on the profile name:

def get_aws_region(profile_name: str) -> str:
  config = configparser.ConfigParser()
  config.read(f"{os.environ['HOME']}/.aws/config")
  profile_section = config[f"profile {profile_name}"]
  return profile_section["region"]
Brandon
  • 1,956
  • 18
  • 18
0

If you use AWS Lambda your code will work while you deploy it, because the Lambda is deployed in a specific region.

Elad Rubi
  • 593
  • 4
  • 7
0

In case you are using Linux, an easy way is that you can create the config file (You should name it config without any extension) at ~/.aws (if .aws directory does not exist create it at user home ~ ) and in that config file add a region just like this.

[default]
region=whatever-aws-region
Hadi Mir
  • 4,497
  • 2
  • 29
  • 31