【Python3入門】boto3を使ってPython3とAWSに触れてみよう!【60分】

記事タイトルとURLをコピーする

ブログ移転に伴い、本記事内の文章、画像を一部修正。(2021/05/14)

こんにちは、CI部の柿﨑と申します。
私はサーバーワークスに入社して3週間ほどですが、とても馴染みやすく毎日リラックスした状態で過ごせております。
このような環境で仕事ができることに感謝感激です!
そんなわけで、今回はPython3入門を題材にしてみます。

さて、今この記事をご覧の方で初めてプログラミングを勉強する際にこういったご経験はないでしょうか?

  • プログラミングを勉強したいけど何となく難しそうだからやらない
  • 技術書などの内容が難しい (いきなり関数の話をされてもうまく想像がつかない)
  • 日本語の技術ブログを見るばかりで公式ドキュメントを見る気が起きない
  • Hello Worldを出力してみたものの、ここから先どうすればいいのか分からない

あると思います!

かくいう私も入り口の部分でとても苦労しました。
プログラミングはあくまでも手段ですのでその先に実現したいことがなければ、なかなか事が運びません。
そのため、今回はboto3と呼ばれるライブラリを活用して、なるべくシンプルに分かりやすく、Python3についてお伝えできればと思います。

本記事の対象者

  • AWSおよびAWS CLIを触ったことがあり、何となくでもPython3が気になる方

本記事のコンセプト

  • シンプルな題材でPython3に触り、AWS上で簡単にできることからやる
  • boto3ドキュメントを活用する

前提条件

  • Windows 10にてAWS CLIの実行環境がある
  • Python3にてHello Worldを出力できる環境がある
    • 私はVSCodeを使いますが、適宜、やりやすい環境を使ってください
  • EC2をいつでも構築できる

目次

  1. Python3用のIAMユーザーを作成
  2. AWSの情報をPython3で取得してみよう
  3. Python3で取得する情報を見やすくしよう
  4. コードを改善してみよう
  5. さいごに

1.Python3用のIAMユーザーを作成

まずは、以下の画像に沿ってPython3を動かすためのIAMユーザーを作成します。
すでにご存じの方も多いと思われるので、ここはサラっといきます。
※権限の強いIAMユーザーをお持ちであれば、そちらを使っていただいても構いません。

コマンドプロンプトなどで、上記のアクセスキーID(以下アクセスキー)とシークレットアクセスキー(以下シークレットキー)をaws configureに入力後、
aws sts get-caller-identityコマンドにて、自身のIAMユーザー情報が出力されることをご確認ください。
※本記事のコンセプトに従って、独自profileを利用するパターンは記載しません。

aws configure
実行結果
AWS Access Key ID [********************]: アクセスキー入力
AWS Secret Access Key [********************]: シークレットキー入力
Default region name [ap-northeast-1]: 対象のリージョン名を入力 ※AWSリソースが何もないリージョンだとやりやすいです。
Default output format [None]: 未入力でEnter
aws sts get-caller-identity
実行結果
{
"UserId": "foo",
"Account": "hogehoge",
"Arn": "arn:aws:iam::hogehoge:user/python3"
}

2.AWSの情報をPython3で取得してみよう

手始めにVPC情報を出力してみます。
Python3でAWS環境を操作するには、boto3と呼ばれるライブラリが必要です。

boto3ドキュメント

boto3をインストールし、Python3のコード内で呼び出してあげることで使えるようになります。
まずは下記コマンドを実行してインストールします。

pip install boto3

正常にインストールが完了したら、任意のフォルダに下記の内容でPython3ファイルを作成します。

# インストールしたライブラリを使えるようにインポートする
import boto3

# AWSリソースを操作する準備(クライアントの作成)
ec2_client = boto3.client('ec2')

# VPC情報を出力する
print (ec2_client.describe_vpcs())
上記コード内にアクセスキーおよびシークレットキーの記載はないですが、AWS CLIを使用するローカルユーザーのフォルダ配下にある
\.aws\config\.aws\credentialsからboto3が認証情報を読み取ってくれます。
この3行のコードを実行すると、以下キャプチャ内のターミナルに表示されるようなVPC情報が出力されます。
f:id:swx-kakizaki:20210514222531j:plain
上記コードの流れをドキュメントのトップページから照らし合わせると以下のようになります。
まずはClientを押下。
f:id:swx-kakizaki:20210514211029j:plain
すると先ほどのコードの先頭2行が確認できます。
f:id:swx-kakizaki:20210514211201j:plain
上記ページ内でdescribe_vpcs()を押下。
f:id:swx-kakizaki:20210514211405j:plain
こちらで先ほどのコードの3行目を確認できます。
サンプルコードでは引数を渡していますが、今回は引数なしで実行していました。
f:id:swx-kakizaki:20210514211608j:plain
こちらのページをもう少し下にスクロールすると、コマンド実行時に得られる返り値が記載されています。
基本的にはこの返り値を参照して必要な情報があるのかを確認します。
もしVPC IDを取得したい場合は、'VpcId'の項目で探してみると記載がありますね!
(以下の画像からさらに下へスクロールすると説明もあります。)
こうして実際に得られた結果と見比べてみると理解が深まるものです。
f:id:swx-kakizaki:20210514211903j:plain
ではここで、EC2インスタンスのインスタンスIDを取得してみようと思います。
※対象リージョンにEC2インスタンスがない場合は、適当なものを1台作成してください。

まずは必要な情報を取得できそうなコマンドをEC2 Clientのページから探してみます。
情報を取得したり参照するコマンドは、describeから始まるものが多いため文字検索などをすると以下が見つかります。
f:id:swx-kakizaki:20210514213717j:plain
説明を読むとこちらのコマンドでインスタンス情報を教えてくれそうです。
f:id:swx-kakizaki:20210514214112j:plain
次にこちらのコマンドの返り値にインスタンスIDが含まれているか、下にスクロールして確認すると目的の記述を確認できるかと思われます。
f:id:swx-kakizaki:20210514213930j:plain
利用するべきコマンドが見つかりましたので、先ほどのコードを少し編集して実行してみます。
# インストールしたライブラリを使えるようにインポートする
import boto3

# AWSリソースを操作する準備(クライアントの作成)
ec2_client = boto3.client('ec2')

# VPC情報を出力する
#print (ec2_client.describe_vpcs())
# EC2情報を出力する
print (ec2_client.describe_instances())
実行結果は記載しませんが、出力がバーっと流れたのではないでしょうか?
その中にインスタンスIDがあるはずです。
しかし、これでは要らない情報が多すぎます。どうにかしたいところです。

3.Python3で取得する情報を見やすくしよう

何も指定せずにコマンドを実行するだけでは目的の情報は取得できているものの見づらいです。
どうにかしてインスタンスIDだけを出力したいと思うはずです。
そういった場合は以下のように必要な情報だけを指定します。
# インストールしたライブラリを使えるようにインポートする
import boto3

# AWSリソースを操作する準備(クライアントの作成)
ec2_client = boto3.client('ec2')

# VPC情報を出力する
#print (ec2_client.describe_vpcs())
# インスタンスIDを出力する
print (ec2_client.describe_instances()['Reservations'][0]['Instances'][0]['InstanceId'])
早速、意味不明ですね。(初心者の頃の私ならそう思うはず。)
最後の行に着目しますと、ec2_client.describe_instances()コマンドのあとにいろいろとくっついていることが分かります。
あえてこのような書き方をしていますが、インスタンスIDが1つだけ出力されるはずです。
ここで改めてboto3ドキュメントの返り値の項目を確認すると以下のような記述があるかと思われます。
f:id:swx-kakizaki:20210514214451j:plain
これは返り値の型を表しています。
dict型と呼ばれる型はKeyとValueが組み合わさったデータ型の1種で、Keyに対応したValueが格納されています。
(例として、AWSリソースに付けるタグを思い浮かべていただければと思います。)
今回のコードでは以下のように取得する値を指定しています。
f:id:swx-kakizaki:20210514215349j:plain
お次は[0]なんて聞いてないよ!となりそうです。
こちらはlist型のデータの位置を示す値となっており、[0]はlist内にある1番目のデータを指します。
list型は複数のデータをひとまとめにすることができるデータ型です。
list型のデータの位置を[0][5]と指定してあげることで、1番目や6番目のデータを取り出すことができます。
私の環境ではEC2インスタンスが複数台作成されています。
その複数台あるEC2インスタンス1台1台の情報が、返り値内のlist型のデータとして順番に格納されているわけであります。
つまり、['Reservations'][0]['Instances'][0]['InstanceId']の意味は、
'Reservations'Keyの1番目のValueにある、'Instances'Keyの1番目のValueにある'InstanceId'Keyを指定しています。
結果、'InstanceId'KeyのValue = インスタンスIDだけが出力されます。

4.コードを改善してみよう

print (ec2_client.describe_instances()['Reservations'][0]['Instances'][0]['InstanceId'])
この1行、明らかに可読性が悪くないでしょうか。
ごちゃごちゃしているし、list型の1番目のデータしか出力されません。
2番目のデータを出力するためにわざわざ[1]と書き換えるのは面倒です。
データが1000個あったら0から999まで書かなければいけません( ^ω^)・・・。

このように初心者ながらもやみくもにコードを書いていくことで、さまざまな問題点が出てきます。
早速、解決してみると以下のようなコードになります。
# インストールしたライブラリを使えるようにインポートする
import boto3

# AWSリソースを操作する準備(クライアントの作成)
ec2_client = boto3.client('ec2')

# Describe結果を変数へ格納
ec2_data = ec2_client.describe_instances()
# ec2_data['Reservations']のlistを1つずつ取り出す
for reservation in ec2_data['Reservations']:
    # reservation['Instances']のlistを1つずつ取り出す
    for instance in reservation['Instances']:
        # 上記で取り出されたデータのインスタンスIDを出力する
        print (instance['InstanceId'])
こちらも出力結果は割愛しますがfor文と呼ばれる文法を使うことにより、まとまったデータを1つずつ取り出すことができます。
このコードでは指定したリージョンの全インスタンスIDが出力されます。

print (ec2_client.describe_instances()['Reservations'][0]['Instances'][0]['InstanceId'])

ここで、上記のコードからどのように変わったかを文章で表しますと、   ec2_client.describe_instances()コマンドの返り値が、変数ec2_dataに格納され、
ec2_client.describe_instances()['Reservations']と記載していたものが、ec2_data['Reservations']となり、for文で1つずつデータを取り出しています。
for文ではec2_data['Reservations']のlist型データが1つずつ変数reservationに格納され、その中のfor文でreservation['Instances']としてlist型データになっているEC2インスタンスの情報を変数instanceに格納しています。
こうして階層を掘っていった先でinstance['InstanceId']と指定してあげることでインスタンスIDが出力されます。
このようにインスタンスIDを出力できるようになると、EC2を起動/停止する関数にインスタンスIDを渡して連携することができたりします。
(EC2を起動/停止するコマンドは、今回と同じ要領で探せばすぐ見つかります。)
そもそも特定のインスタンスIDだけほしい!という状況でしたら、boto3ドキュメントを参考にec2_client.describe_instances()の引数をいじってみたりなど、できることの幅が広がってくるのではないかと思われます。

5.さいごに

本記事で私が伝えたかったことは、

・不格好なかたちであれとにかくプログラミングをすることが一番の勉強になること
・公式ドキュメントの使い方に慣れていこう

という2点です。
私がPythonに触り始めたころは、関数を使わずに上から下までズラっとコードを書いていた時期もございました。
ある日、1度書いた処理をもう1度書く必要が出てきたときに関数の必要性を理解したものです。
本記事のようにたった数行のコードを書くだけでもコードの改善点が出てきます。
今回は私がプログラミングの入り口を見出せなかった時期にこんな記事があればうれしいなという想いをかたちにしました。

本記事が、皆様のお役に立てれば幸いでございます。

柿﨑 拓人 (記事一覧)

クラウドインテグレーション部

AWS移行案件の要件定義~構築をメインに担当。
最近ボルダリングをはじめました。