【初心者向け】Zaif API×Pythonでプチフィンテック6 異常への対応その1

今回は前回の予告通り、サーバへのアクセス時に何らかの異常が発生し、処理が正しく行えない場合に適切に対処する方法について紹介したいと思います。

<スポンサーリンク>

発生し得る異常

さて、異常への対応方法を実装する前に、まずはどのような異常が発生し得るのかを説明します。

結論から言ってしまうと、公開系のAPI利用時に発生する異常は、①サーバ管理範疇の異常と②範疇外の異常の2つがあります

①サーバ管理範疇の異常とは、サーバが生きている状況下で、サーバ内部の処理に異常があったり、あるいは、プログラムからの接続方法が正しくないために、サーバが「エラーですよ」と返してくれる異常のことです。

一方、②サーバ管理範疇外の異常とは、サーバに通信が集中してダウンしてしまった場合など、サーバが「エラーですよ」と返すことすらできない状態で、アクセスが成立しない異常を指します。

今回は、この②に対する実装を行うこととし、①の異常に対する実装は次回紹介したいと思います。

異常発生時のプログラムの挙動

実装の前に、②の異常が発生した場合、プログラム上で何が起こるのか順を追って説明していきます。

まず、前回の最終形のプログラムを以下に示します。

import requests

CURRENCY_PAIR = 'mona_jpy'

response = requests.get('https://api.zaif.jp/api/1/last_price/' + CURRENCY_PAIR)

print(response.text)

仮にサーバがダウンしているとして、このプログラムがどのように動くのか、1行ずつ見て行きましょう。

まず、1行目のインポート文は、あくまでもプログラム内部の処理ですから、サーバの生死に関係なく実行されます。次の3行目も同様です。

そして5行目でgetメソッドを使ってサーバにアクセスするわけですが、ここでサーバがダウンしていることから、アクセス結果を取得することができません。つまり、ここで異常が発生するわけです。

この際、Pythonプログラムでは「例外(Exception)」というものをプログラム実行側に返します。「例外」とはつまり、「異常」を意味します。そしてここでプログラムは処理を停止してしまいます。

と、言葉だけで説明してもイメージがつかないと思いますので、実際に例外を発生させてみましょう。

といっても、サーバをダウンさせるわけにもいきませんので、正しいURLの代わりにZaifドメイン外の存在しないものを指定して、プログラムを実行してみます。

ここでは、5行目の

‘https://api.zaif.jp/api/1/last_price/’

を、

‘https://api.zaif.jpp/api/1/last_price/’

というように、「p」を1つ増やしたURLにアクセスしてみます。

すると、以下のような結果がコンソールに表示されると思います。(非常に長いため、冒頭部分のみ抜粋しています。)

C:\Users\user\Miniconda3\python.exe C:/Users/user/PycharmProjects/tradebot/publictest1.py
Traceback (most recent call last):
  File "C:\Users\user\Miniconda3\lib\site-packages\urllib3\connection.py", line 141, in _new_conn
    (self.host, self.port), self.timeout, **extra_kw)
  File "C:\Users\user\Miniconda3\lib\site-packages\urllib3\util\connection.py", line 60, in create_connection
    for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
  File "C:\Users\user\Miniconda3\lib\socket.py", line 745, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 11001] getaddrinfo failed

上記の最終行にある、「socket.gaierror」というものが、実際に発生したExceptionです。

実行したコードは7行目までありましたが、5行目でこのようなExceptionが発生しているため、そこで処理が終了してしまい、7行目のprint文が実行されていないことがお判りになるかと思います。

それでは、例外が発生した場合、単に異常終了させるのではなく、それを踏まえて意図した処理を実行させるためには、どのような対応を行えばよいのでしょうか?

Pythonでは例外発生時にそれをキャッチして、処理を継続させる方法があります

実装

ここまでの話を踏まえて、例外処理の実装を行っていきましょう。

まずは、新規にPythonファイルを作成し、前回のプログラムをコピーしておきます。ここでは、publictest2という名称でファイルを作成しました。

そして、例外対応を行う「try-except構文」というものを使って、プログラムを以下のように修正します。

import requests

CURRENCY_PAIR = 'mona_jpy'

try:
    response = requests.get('https://api.zaif.jpp/api/1/last_price/' + CURRENCY_PAIR)
    print(response.text)

except:
    print('例外発生')

見ての通り、response・・・の行とprint(response・・・の行を、インデントを使うことによってtryブロックの中に入れ込んでいます。

この状態で、tryブロック内で例外が発生すると、その下に追記しているexceptというブロックに制御が移り、その中の処理が実行されることになります。今回の場合、「例外発生」という文字列が表示されます。

例外処理の実装は以上です。

テスト実行

それでは、実装した内容が正しく動くか、実際にプログラムを実行してみましょう。

現在、getメソッドで取得対象としているURLはあえて誤ったものにしているため、getメソッド実行時に例外が発生し、その結果を受けて「例外発生」という文字列がコンソールに表示されるはずです。

プログラムを実際に実行してみますと、

となり、確かに例外の発生を受けて、意図した通りの処理が行われています。

念のために、URLを正しいものに置き換えて、正常パターンでも意図したとおりにプログラムが動作するか、確認しておきましょう。

無事に動きましたね。

終わりに

今回は、例外発生時にプログラムを異常終了させてしまうのではなく、その後も意図した処理を行わせるための方法として、try-except構文を紹介しました。

今回の例ではtry-exceptの効果をそれほど実感できないかもしれません。しかしながら、今後取引を自動化する中で、ループ処理により処理を繰り返し行わせる必要があります。その際、例外対応を実装しておくことで、繰り返し処理を途切れさせず、継続的に実施させることが可能になります。

さて、今回の記事の冒頭で、異常は2種類あると書きましたが、次回の記事ではもう1パターンの異常発生時の対応について紹介していきたいと思います。

カテゴリ:フィンテック
<スポンサーリンク>

シェアする

フォローする