標準ライブラリを使用したネットワーク リクエスト

PythonBeginner
オンラインで実践に進む

はじめに

運用業務では、Web サービスが利用可能かどうかを確認する作業がよくあります。requests などのサードパーティーライブラリは広く使われていますが、制限された環境では Python の標準ライブラリだけに頼らなければならない場合があります。

この実験では、Python の標準ライブラリモジュール urllib を使って、簡単な接続チェッカーを作成します。追加の依存関係がなくても、実用的な運用ツールを構築できることを確認します。

この実験を終えると、次のことができるようになります。

  • urllib.request モジュールをインポートする。
  • URL を確認する関数を定義する。
  • HTTP ステータスコード(例:200 OK)を取得する。
  • サーバーエラーやホストに接続できない場合などの例外を処理する。
  • 利用者に分かりやすいステータスメッセージを表示する。

モジュールをインポートする

このステップでは、まず Python スクリプトを作成し、必要なモジュールをインポートします。urllib.request モジュールは、URL を開くための Python 組み込みツールです。マウスの代わりにコードで操作できる Chrome や Firefox などの Web ブラウザーだと考えてください。このモジュールを使うと、スクリプトからインターネット上のデータを取得できます。

運用業務では、多くのシステムが HTTP ベースの API やヘルスエンドポイントを提供しているため、この知識が役立ちます。後でチームがサードパーティーライブラリを採用する場合でも、標準ライブラリのツールを理解しておくと、リクエストとレスポンスの基本的な仕組みをより明確に把握できます。

まず、正しいディレクトリにいることを確認します。ターミナルを開き、プロジェクトフォルダーに移動してください。

cd ~/project

次に、nano テキストエディター(または任意のエディター)を使って、connectivity_check.py という名前の新しい Python ファイルを作成します。

nano connectivity_check.py

Python でライブラリを使うには、最初にインポートする必要があります。次の行をファイルの先頭に追加してください。ここでは、リクエストを処理するために urllib.request を、後で発生する可能性のあるエラーを処理するために urllib.error をインポートします。

import urllib.request
import urllib.error

Ctrl+O を押し、続けて Enter を押してファイルを保存します。その後、Ctrl+X を押して nano を終了します。

cat コマンドを使うと、ファイルの内容を確認できます。

cat connectivity_check.py

関数を定義する

インポートの準備ができたので、次はコードの構造を整えます。ロジックを関数にまとめることは、よく使われる実践方法です。これにより、コードを再利用しやすく、テストもしやすくなります。

運用スクリプトでは、同じ処理を複数の対象に対して実行することがよくあるため、関数が特に役立ちます。ネットワークチェックを関数にまとめておけば、コードを重複させずに異なる URL に対して呼び出せます。

このステップでは、引数として URL 文字列を受け取る check_url という名前の関数を定義します。

connectivity_check.py をもう一度開きます。

nano connectivity_check.py

インポート文の下に、次の関数定義を追加してください。ここでは、Python で「何もしない」ことを示すプレースホルダーの pass 文だけを追加します。具体的なロジックは次のステップで実装します。

import urllib.request
import urllib.error

def check_url(url):
    print(f"Checking connectivity for: {url}")
    ## Logic will go here
    pass

ファイルを保存してエディターを終了します(Ctrl+O、Enter、Ctrl+X)。

この構造が、これから作成する処理の基礎になります。check_url 関数は url という 1 つのパラメーターを受け取ります。このパラメーターには、確認対象の Web サイトのアドレス(例:"https://www.google.com")を指定します。

リクエストを送信する

このステップでは、リクエストを送信して HTTP ステータスコードを取得する基本ロジックを実装します。HTTP ステータスコード 200 は、通常「OK」または成功を意味します。

HTTP リクエストは、クライアントとサーバーの間で行われる通信です。今回のスクリプトがクライアントになります。スクリプトは URL にリクエストを送り、サーバーのレスポンスを待ち、次に何をするかを決める前に、ステータスコードなどのメタデータを確認します。

URL を開くには urllib.request.urlopen() を使用します。この関数はレスポンスオブジェクトを返します。レスポンスオブジェクトの .getcode() メソッドを使うと、ステータスコードを取得できます。

connectivity_check.py を開きます。

nano connectivity_check.py

check_url 関数を、次の内容になるように更新してください。サーバーが応答しない場合にスクリプトが停止したままにならないよう、5 秒のタイムアウトを設定しています。

import urllib.request
import urllib.error

def check_url(url):
    print(f"Checking connectivity for: {url}")

    ## Open the URL with a 5-second timeout
    response = urllib.request.urlopen(url, timeout=5)

    ## Get the status code
    status_code = response.getcode()

    print(f"Status Code: {status_code}")

注記:この段階では、URL が無効だったりサーバーが停止していたりすると、まだエラー処理を追加していないため、スクリプトはクラッシュします。この問題は次のステップで解決します。

ファイルを保存してエディターを終了します。

エラーを処理する

ネットワークプログラミングでは、予期しない問題が起こります。サーバーが停止したり、DNS ルックアップに失敗したり、インターネット接続が切断されたりすることがあります。urlopen が失敗すると、例外が発生します。スクリプトを安定して動作させるには、try...except ブロックを使ってこれらの例外を処理する必要があります。

実際の監視では、障害の種類を区別することが重要です。サーバーが 500 を返した場合は、サーバーには到達でき、サーバー自身が内部問題を報告しています。一方、URLError は、リクエストが利用可能な HTTP エンドポイントに到達しなかったことを示す場合が多くあります。運用担当者は、これらを異なる種類のインシデントとして扱います。

ここでは、次の 2 種類のエラーを処理します。

  • urllib.error.HTTPError:サーバーは応答したものの、エラーコードを返した場合(例:404 Not Found、500 Server Error)。
  • urllib.error.URLError:サーバーにまったく到達できなかった場合(例:インターネットに接続されていない、ドメインが間違っている)。

try...except ブロックは、安全網のようなものです。インターネット接続が切れるなどの問題が起きても、コード全体がクラッシュするのではなく、except ブロックに移ります。そこでエラーを捕捉し、役立つメッセージを表示できます。

connectivity_check.py を開きます。

nano connectivity_check.py

リクエスト処理を try ブロックで囲むように、関数を変更してください。

import urllib.request
import urllib.error

def check_url(url):
    print(f"Checking connectivity for: {url}")

    try:
        ## Attempt to open the URL
        response = urllib.request.urlopen(url, timeout=5)
        status_code = response.getcode()
        print(f"Success! Status Code: {status_code}")

    except urllib.error.HTTPError as e:
        ## Server responded with an error (e.g., 404, 500)
        print(f"HTTP Error: {e.code}")

    except urllib.error.URLError as e:
        ## Failed to reach the server
        print(f"URL Error: {e.reason}")

このコードは、まず try ブロック内の行を実行します。エラーが発生すると、Python は try ブロックの実行を停止し、該当する except ブロックに移ります。

ファイルを保存してエディターを終了します。

スクリプトをテストする

最後のステップでは、関数を呼び出す main ブロックを追加して、スクリプトを実行可能にします。これにより、ターミナルからスクリプトを直接実行できます。

if __name__ == "__main__": というパターンは、再利用可能な関数と、直接実行したときに動かすコードを分ける Python の慣例です。この設計により、別のスクリプトから check_url をインポートしても、テスト用の呼び出しが自動的に実行されないため、後で再利用しやすくなります。

動作が確認できる URL(https://www.example.com など)でテストします。また、エラー処理の動作を確認するために、存在しない URL も試せます。

connectivity_check.py を開きます。

nano connectivity_check.py

ファイルの末尾に、次のコードを追加してください。

if __name__ == "__main__":
    ## Test with a valid URL
    target_url = "https://www.example.com"
    check_url(target_url)

    print("-" * 20)

    ## Test with an invalid URL to see error handling
    invalid_url = "https://www.this-domain-does-not-exist-12345.com"
    check_url(invalid_url)

if __name__ == "__main__": ブロックにより、このコードはスクリプトを直接実行したときだけ実行されます。別のスクリプトでモジュールとしてインポートした場合は実行されません。

ファイルを保存してエディターを終了します。

次に、スクリプトを実行して結果を確認します。

python3 connectivity_check.py

次のような出力が表示されます。

Checking connectivity for: https://www.example.com
Success! Status Code: 200
--------------------
Checking connectivity for: https://www.this-domain-does-not-exist-12345.com
URL Error: [Errno -2] Name or service not known

(注記:無効な URL に対する正確なエラーメッセージは、ネットワーク環境によって少し異なる場合があります)。

まとめ

この実験では、Python の標準ライブラリを使ってネットワーク接続チェッカーを作成しました。次のことを学びました。

  • モジュールのインポート:urllib.request と urllib.error を使用しました。
  • HTTP リクエストの送信:urlopen を使って Web サーバーに接続しました。
  • レスポンスの処理:HTTP ステータスコードを取得し、サービスが利用可能かどうかを確認しました。
  • エラーの管理:try...except ブロックを実装して HTTPError と URLError を処理し、ネットワーク障害に対して安定して動作するスクリプトを作成しました。

このスキルは、外部依存関係をインストールできない環境で、監視スクリプト、ヘルスチェック、簡単な Web スクレイパーを作成するための基本になります。