投稿者: sumito.tsukada

  • Flaskにおける特定のルートのログ出力の無効化について: AWS EC2/ECS

    Flaskにおける特定のルートのログ出力の無効化について: AWS EC2/ECS

    FlaskはPythonで開発された軽量なWebフレームワークで、そのシンプルさと拡張性から多くの開発者に利用されています。

    今回は、特にAWSのEC2やECSでFlaskを使用している開発者の皆様向けに、ある一般的な問題とその解決策について共有させていただきます。

    サーバーのヘルスチェックは重要な部分であり、私たちはそのためのエンドポイント/healthzを定期的にポーリングしています。

    しかし、これがもたらすログ出力の多さが問題となり、重要な情報が見づらくなることがあります。

    そこで、ヘルスチェックのエンドポイントに関するログだけを無効にする方法について考察しました。

    解決策:特定のルートのログ出力をフィルタリングする

    この問題に対する答えの一つとして、PythonのloggingモジュールのFilterクラスを用いる方法があります。このクラスを継承し、カスタムフィルタクラスを作成します。このフィルタをロガーに追加することで、特定のログメッセージをフィルタリングできます。

    import logging

    class HealthCheckFilter(logging.Filter):
    def filter(self, record):
    return "/healthz" not in record.getMessage()

    ここで定義したHealthCheckFilterクラスは、ログメッセージに/healthzが含まれていない場合にのみTrueを返します。

    したがって、/healthzがメッセージに含まれるログエントリはフィルタリングされ、出力されません。

    そして、このフィルタを適用したいロガーに追加します:

    logger = Logger().getLogger('default')
    logger.addFilter(HealthCheckFilter())

    これにより、ヘルスチェックに関するログ出力が無効化され、ログの可読性が向上します。

    注意点

    この解決策は、特定のロガーに対してのみ適用されます。全体のロガーへの適用はされません。

    例えば、Flaskは内部的にWerkzeugサーバーを利用しており、そのサーバーは自己のロガー(‘werkzeug’)を持っています。

    そのため、もしWerkzeugサーバーからのログもフィルタリングしたい場合は、同様にフィルタを追加する必要があります。

    この記事がAWSのEC2やECSで大規模なFlaskアプリケーションを運用している皆様の一助になれば幸いです。

    特定のエンドポイントのログ出力を制御することで、ログの可読性が向上し、重要な情報へのアクセスが容易になります。

    私たちはまだ学び続けており、他の解決策や改善点があれば、ぜひ共有いただければと思います。

  • AWS CLIでエスケープなしのJSONを送信する

    AWS CLIでエスケープなしのJSONを送信する

    AWS CLIを使って作業を行うとき、しばしばJSON文字列を引数として渡す必要があります。しかし、これが難しい場合もあります。特に文字列内にエスケープが必要な文字(バックスラッシュなど)が含まれている場合です。

    今回は、エスケープなしのJSON文字列をAWS CLIに直接渡す方法を紹介します。

    ヒアドキュメントの使用

    ヒアドキュメント(Here Document)は、シェルスクリプトのリダイレクトの一種で、複数行のテキストを直接スクリプト内に記述するための方法です。

    ヒアドキュメント内部では、一部のエスケープシーケンスが解釈されずバックスラッシュがただの文字として扱われます。

    これを利用すると、バックスラッシュを含む文字列をエスケープせずに直接AWS CLIに渡すことが可能になります。

    具体的には、以下のようにします:

    aws sqs send-message --profile your-profile --queue-url "your-queue-url" --message-group-id "your-message-group-id" --message-body "$(cat <<EOF
    {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
    }
    EOF
    )
    "

    ここで、

    $(cat <<EOF ... EOF)

    がヒアドキュメントの部分で、これが完全に展開された後で

    aws sqs send-message

    コマンドが実行されます。ヒアドキュメント内のJSON文字列はエスケープなしでそのまま扱われるため、特殊文字を含むパスでも問題なくAWS CLIに渡すことができます。

    まとめ

    AWS CLIでエスケープが必要な文字を含むJSONを扱う際には、ヒアドキュメントが非常に便利です。ヒアドキュメントを使うと、エスケープなしで文字列をそのまま扱うことができるので、コマンドラインでの作業が少し楽になります。

  • SSH ProxyJumpを利用した便利な接続方法

    SSH ProxyJumpを利用した便利な接続方法

    SSHを使用してサーバーに接続する際、中継サーバー(bastionホスト)を経由しなければならない場面は珍しくありません。こ

    の手順は煩わしく、特に同じ設定を繰り返し行う必要がある場合、非効率的に感じるかもしれません。

    そんな時に便利なのがSSHのプロキシジャンプ(ProxyJump)機能です。一度のコマンドで中継サーバーを経由してターゲットサーバーに接続することが可能になります。

    設定は以下のように行います。

    まずは、~/.ssh/configに中継サーバーとターゲットサーバーの設定を記述します。

    Host stg-bastion
    Hostname xxxxxxxx
    IdentityFile ~/.ssh/your_identity_file

    Host target-server
    Hostname xxxxxxxx
    IdentityFile ~/.ssh/your_identity_file
    ProxyJump stg-bastion

    ここでは、stg-bastionという名前の中継サーバーに接続し、そこを経由してtarget-serverという名前のターゲットサーバーに接続します。どちらの接続でも同じIdentityFileが使用されます。

    設定を追加したら、以下のコマンドを実行することで、直接target-serverサーバに接続できます:

    ssh target-server

    この機能を使用することで、SSH接続の作業を大幅に効率化できます。あなたもぜひ試してみてください。

    以上、SSH ProxyJumpを利用した便利な接続方法についての記事でした。参考になれば幸いです。

  • jqコマンドでJSONから指定した項目を取得・変換する

    jqコマンドでJSONから指定した項目を取得・変換する

    JSONはウェブのデータ交換形式として広く使われていますが、大量のデータを扱うときはデータをフィルタリングしたり整形したりすることが必要になることがあります。今回は、jqコマンドを使ってJSONから特定の項目を取り出し、新しい形式に整形する方法、特定の条件にマッチするレコードのみを選択する方法、そしてmap関数の使い方を紹介します。

    JSONデータの例

    以下に、我々が今回扱うサンプルのJSONデータを示します:

    {
    "records": [
    {
    "id": 1234,
    "user": {
    "id": 5678,
    "account": "user1@example.com",
    "status": 0,
    "attributes": []
    },
    "attributes": [
    {
    "values": [
    {
    "value": "2023-01-01T00:00:00"
    }
    ],
    "id": 2,
    "name": "Date"
    },
    {
    "values": [
    {
    "value": "AB01"
    }
    ],
    "id": 1,
    "name": "Code"
    }
    ]
    }
    ],
    "meta": {
    "totalCount": 999,
    "page": 1,
    "countPerPage": 1,
    "maxPage": 999
    }
    }

    このデータには複数のレコードが含まれ、各レコードにはuser情報とattributes情報があります。

    jqコマンドで特定の項目を取得

    今回の目的は、各レコードから特定の項目を取得し、それを新しい形式に整形することです。これを達成するために、jqコマンドを使用します。

    以下に、新しい形式にデータを整形するためのjqコマンドを示します:

    jq '[.records[] | {EmployeeNumber: .user.id, Email: .user.account, GradeDate: .attributes[0].values[0].value, Grade: .attributes[1].values[0].value}]' input.json

    このコマンドは以下の操作を行います:

    1. レコード配列の各要素に対して操作を行います。
      (.records[] |)。
    2. 新しいオブジェクトを作成し、その中に指定のキーと値を設定します({EmployeeNumber: .user.id, Email: .user.account, GradeDate: .attributes[0].values[0].value, Grade: .attributes[1].values[0].value})。
    3. すべての新しいオブジェクトを包含する配列を作成します([…])。

    これにより、各レコードは新しい形式のオブジェクトに変換され、すべてのオブジェクトが配列に格納されます。それぞれのオブジェクトは EmployeeNumber、Email、GradeDate、Grade の 4つのフィールドを持ちます。

    特定の条件にマッチするレコードを選択

    また、jqは特定の条件にマッチするレコードだけを選択するためのフィルタリング機能も提供しています。たとえば、statusが0のレコードだけを選択するには、以下のようにします:

    jq '[.records[] | select(.user.status == 0) | {EmployeeNumber: .user.id, Email: .user.account, GradeDate: .attributes[0].values[0].value, Grade: .attributes[1].values[0].value}]' input.json

    このコマンドではselect(.user.status == 0)を使用して statusが0のレコードだけを選択しています。

    map関数の使い方

    関数は、配列の各要素に関数を適用して新しい配列を作成するためのものです。たとえば、各レコードのattributesの中のvaluesを取り出すには以下のようにします:

    jq '.records[] | .attributes | map(.values[].value)' input.json

    このコマンドでは、まず各レコードのattributesを取り出し(.records[] | .attributes)、それからmap関数を使って各attributesの中のvaluesのvalueを取り出しています(map(.values[].value))。

    結論

    このように、jqコマンドは非常に強力で柔軟なツールであり、JSONデータの検索やフィルタリング、変換に最適です。特にselect関数とmap関数は、データのフィルタリングや変換において非常に便利です。

    様々な場面でのデータ操作に活用してみてください。また、jqのドキュメンテーションは非常に充実していますので、さらに高度な操作を学びたい場合はそちらを参照してみてください。

  • Office365-REST-Python-Clientを使用したOneDriveへの1GBファイルのアップロード

    Office365-REST-Python-Clientを使用したOneDriveへの1GBファイルのアップロード

    クラウドストレージのOneDriveにファイルを自動的にアップロードする方法について話します。特にPythonを使ったアプローチに焦点を当てます。この記事は、開発者、データサイエンティスト、またはOneDriveを活用して効率を上げたい人向けに書かれています。

    前提条件

    このチュートリアルでは、Python 3.6以上がインストールされていることを前提とします。また、必要なPythonパッケージをインストールするためにpipも必要です。これらがまだインストールされていない場合は、公式のPythonウェブサイトからダウンロードしてください。

    必要なパッケージ

    まず最初に、このプロジェクトで必要となるPythonパッケージをインストールしましょう。今回はOffice365のREST APIクライアントライブラリを使用します。このパッケージは、OneDriveとの連携を容易にします。以下のコマンドを実行してパッケージをインストールしましょう:

    pip install Office365-REST-Python-Client

    この操作はスクリプトを実行する前に行ってください。

    Pythonスクリプトの作成

    以下に、Pythonを使用してOneDriveにファイルをアップロードするための基本的なスクリプトを提供します。

    (インデントが崩れてしまってすみません。。)

    from office365.runtime.auth.user_credential import UserCredential
    from office365.runtime.client_request_exception import ClientRequestException
    from office365.onedrive.driveitems.drive_item import DriveItem
    from office365.graph_client import GraphClient
    from office365.runtime.auth.authentication_context import AuthenticationContext
    import os
    
    
    def get_onedrive_context_using_user():
    tenant = "xxxxxxxxxx"
    authority_url = f"https://login.microsoftonline.com/{tenant}"
    client_id = "xxxxxxxxxx"
    client_secret = "password"
    
    context_auth = AuthenticationContext(authority_url)
    context_auth.acquire_token_for_app(client_id, client_secret)
    
    client = GraphClient(context_auth)
    return client
    
    
    def create_onedrive_directory(client, dir_name: str):
    """
    Creates a folder in the OneDrive directory.
    """
    if dir_name:
    drive_item = DriveItem(client)
    drive_item.name = dir_name
    drive_item.folder = {"childCount": 0}
    return client.me.drive.root.children.add(drive_item)
    
    
    local_path = "1G.csv"
    dir_name = 'test-tsukada-dir-hoge'
    chunk_size = 50000000
    
    def print_upload_progress(range_pos):
    print("{0} bytes uploaded".format(range_pos))
    
    try:
    client = get_onedrive_context_using_user()
    create_onedrive_directory(client, dir_name)
    remote_drive = client.me.drive.root.get_by_path(dir_name)
    
    with open(local_path, 'rb') as f:
    remote_drive.resumable_upload(f, chunk_size=chunk_size, chunk_uploaded=print_upload_progress).get().execute_query()
    print(f"File {local_path} has been uploaded")
    except ClientRequestException as ex:
    print(ex)

    このスクリプトは OneDrive 上のルートにフォルダを作成し、指定したファイルをそのフォルダにアップロードします。アップロードの進行状況はコールバック関数print_upload_progress を用いて表示します。

    ただし、このコードは Azure AD のアプリ登録で取得した client_id と client_secret を使用していますので、それぞれ適切な値に置き換えてください。また、Azure AD のテナントIDも必要となります。

    スクリプトの実行

    スクリプトを実行するには、以下のコマンドをターミナルまたはコマンドプロンプトから実行します:

    python upload_to_onedrive.py

    これで、指定したファイルがOneDriveに自動的にアップロードされます!

    まとめ

    Pythonを使用してOneDriveにファイルを自動アップロードする方法について解説しました。この方法は、定期的なバックアップ、大量のファイルの移行、または一般的なファイルの管理など、さまざまなシナリオで役立ちます。

  • PandasとSnowflakeでNULL値を扱う

    PandasとSnowflakeでNULL値を扱う

    PandasとSnowflakeでNULL値を扱う

    PythonのPandasライブラリとSnowflakeデータベースの間でデータを移動させる場合、 NULL値の扱いはしばしば問題になります。 この記事では、Pandasのデータフレーム内でのNULL値の表現と、 その値をSnowflakeに書き込む方法を説明します。

    PandasでのNULL値

    Pandasでは、データフレーム内の欠損値は None または numpy.nan で表現されます。 これらの値は、数値データだけでなく日付/時刻データに対しても使用できます。 以下のコードスニペットは、データフレームの特定の位置に numpy.nan を設定する方法を示しています。

    import numpy as np
    
    # Set a value in the TIMESTAMP_NTZ column to NaN
    df.loc[0, 'your_timestamp_column'] = np.nan

    このコードは、データフレームの ‘your_timestamp_column’ 列の0行目の値を numpy.nan に設定します。

    NULL値をSnowflakeに書き込む

    PandasからSnowflakeへのデータの書き込みは、 Snowflake-connector-pythonの write_pandas 関数を使用して行うことができます。 この関数は、Pandasの Nonenumpy.nan の値をSnowflakeの NULL として解釈します。 以下のコードスニペットは、上で修正したデータフレームをSnowflakeに書き込む方法を示しています。

    from snowflake.connector.pandas_tools import write_pandas
    
    # Then write the DataFrame to Snowflake
    write_pandas(sf_conn, df, snowflake_table)

    このコードは、sf_conn(Snowflakeへの接続)を使用して、データフレーム dfsnowflake_table という名前のテーブルに書き込みます。 この方法により、Pandasデータフレーム内でNULL値を簡単に扱い、その値をSnowflakeに適切に書き込むことができます。 以上、PythonとPandas、そしてSnowflakeを活用してデータをより柔軟に扱う方法についてお伝えしました。

  • SQL: Null値の扱い方 – COALESCE関数を使った実践的なガイド

    SQL: Null値の扱い方 – COALESCE関数を使った実践的なガイド

    データベースを操作するとき、null値をどのように扱うかは一般的な問題です。実際、Nullはデータが存在しないことを示し、これが意図的である場合もあれば、データが不足しているためである場合もあります。したがって、null値を適切に処理することはデータ管理の重要な部分です。 今日は、SQLのCOALESCE関数を用いたnull値の扱い方について解説します。COALESCE関数は、引数のリストから最初の非null値を返します。

    COALESCE関数とは?

    COALESCE関数は、引数リストから最初の非null値を返すSQLの関数です。COALESCE関数は、以下のように使用します:

    COALESCE(value1, value2, ..., valueN)

    value1からvalueNまでの値が順番に評価され、最初の非null値が返されます。すべての値がnullの場合、COALESCE関数はnullを返します。

    COALESCE関数の具体的な使用例

    例として、以下のテーブルを考えてみましょう。

    CREATE TABLE Employees (
    id INT PRIMARY KEY,
    firstName VARCHAR(100),
    lastName VARCHAR(100),
    email VARCHAR(100)
    );

    このテーブルで、firstNameとlastNameのどちらかがnullの場合に、その代わりに’email not provided’という文字列を表示したいとします。この場合、COALESCE関数を使用できます。

    SELECT id, COALESCE(firstName, 'email not provided') AS firstName, COALESCE(lastName, 'email not provided') AS lastName FROM Employees;

    これにより、firstNameまたはlastNameがnullの場合、その値の代わりに’email not provided’と表示されます。

    数値データに対するCOALESCE関数の使用

    COALESCE関数は数値データにも適用できます。たとえば、ある数値の列がnullの場合、その代わりに0を表示したいとします。この場合もCOALESCE関数を使用できます。

    SELECT id, COALESCE(salary, 0) AS salary FROM Employees;

    これにより、salaryがnullの場合、その値の代わりに0が表示されます。

    まとめ

    COALESCE関数はSQLの強力なツールであり、null値を簡単に扱うことができます。適切なデフォルト値を設定することで、データの一貫性を維持しつつ、欠損データを適切に扱うことができます。SQLのクエリにCOALESCE関数を組み込むことで、データ分析やレポート生成のプロセスをよりスムーズに、より効率的に進めることが可能になります。 また、特定のデータタイプに対して特定のデフォルト値を設定することも可能です。例えば、数値型がnullの場合には0を、文字列型がnullの場合には空文字列(”)をデフォルト値とするなど、データの種類により異なる扱い方をすることができます。

    SELECT
    COALESCE(NENDO, '') AS NENDO,
    COALESCE(HANKI, '') AS HANKI,
    COALESCE(OROSI_DAIHYO_CD, '') AS OROSI_DAIHYO_CD,
    COALESCE(MSDSH_HANTEI_JISSEKI_NEW, 0) AS MSDSH_HANTEI_JISSEKI_NEW,
    FROM YOUR_TABLE;

    以上のように、COALESCE関数を使用すると、一貫性を保ったままかつ効率的にデータベース内のnull値を扱うことができます。COALESCE関数のこのような特性は、データベース操作の質を向上させ、データ解析の正確性を保つ上で重要な役割を果たします。


    これで、SQLのCOALESCE関数についての基本的なガイドと具体的な使用例を提供しました。この記事が、日々のデータベース操作で遭遇する可能性のあるnull値の問題に対する理解と解決の助けになることを願っています。COALESCE関数をうまく使いこなして、より洗練されたデータ処理を実現していけたら幸いです。

  • No space left on device エラーへの対処法

    No space left on device エラーへの対処法

    概要

    今回は、Pythonパッケージのインストール時に遭遇する可能性のある一つの問題、 「No space left on device」エラーとその対処法について説明します。 このエラーが発生する場合、最初に疑うべきは、確かにストレージ容量が足りていない可能性です。 しかし、たとえストレージに十分な空き容量がある場合でも、特定の状況下ではこのエラーが発生します。その解決方法を説明します。

    解決策への道筋

    Pythonパッケージのダウンロードやインストール時に、一時的なファイルが作成されます。 これらの一時的なファイルは通常 /tmp ディレクトリに保存され、大規模なパッケージをインストールする際に /tmp の容量を超えてしまうことがあります。これがエラーの原因となります。 解決策としては、一時ファイルの保存場所を /tmp から別のディレクトリに変更します。これは、環境変数 TMPDIR を設定することで実現します:

    export TMPDIR=/var/tmp

    そして、再度パッケージのインストールを試みます:

    pip3 install --no-cache-dir accelerate

    注意点として、この変更は現在のシェルセッションにのみ適用されます。システム全体への恒久的な変更を行いたい場合は、適切な設定ファイル(例えば ~/.bashrc~/.bash_profile)に上記の export 行を追加します。

    まとめ

    本記事では、「No space left on device」エラーが発生する原因と対処法について解説しました。 この情報が皆様の問題解決の一助となり、よりスムーズにPythonを利用してビジネスを推進する助けとなれば幸いです。

  • Docker:未タグ付けイメージの効率的な削除方法

    Docker:未タグ付けイメージの効率的な削除方法

    Dockerの活用において、管理が複雑化しやすい一部分として、未タグ付け(”dangling”または”untagged”とも表現される)のイメージが存在します。 これらのイメージは新たなビルドにより生成される一方で、古いイメージのタグが剥がれることで生じます。 これらの未タグ付けのイメージが増えると、ディスクスペースの消費が増大し、リソースの効率的な使用が妨げられます。 そこで、本記事では未タグ付けのDockerイメージを一括で削除する方法について説明します。具体的な手順は以下の通りです。

    docker rmi $(docker images -f "dangling=true" -q)

    このコマンドについて詳しく見ていきましょう。

    • docker images -f "dangling=true" -q: このコマンドは、未タグ付けのイメージのIDを一覧表示します。フィルタリングオプション-fで”dangling=true”を指定し、出力オプション-qでIDのみを出力します。
    • docker rmi: このコマンドは、指定したイメージを削除します。前述のコマンドで取得したイメージIDをこのコマンドに渡します。

    このコマンドラインを実行することで、未タグ付けのイメージを効率的に削除できます。 ただし、注意すべき点として、この操作にはDockerデーモンへの管理者権限が必要です。 また、使用しているDockerのバージョンによっては、”dangling”ではなく”untagged”という語句を使用する必要があるかもしれません。 以上が、Dockerで未タグ付けのイメージを一括で削除する方法になります。 この方法を用いて、ディスクスペースの有効活用を図り、システムの効率的な運用を実現しましょう。

  • GitHub接続エラーとその解決方法

    GitHub接続エラーとその解決方法

    GitHubへの接続エラーについて書きたいと思います。これは私自身が遭遇した問題で、その解決策を共有したいと思います。

    問題の概要

    ある日、GitHubにSSH経由で接続しようとしたところ、以下のようなエラーメッセージが表示されました。

    The fingerprint for the RSA key sent by the remote host is SHA25

    このメッセージは、GitHubのサーバーから送られてきたRSAキーのフィンガープリントがSHA25と一致しないという意味です。SSHは安全な接続を確保するために、接続先のサーバーから送られてくる公開鍵のフィンガープリントを検証します。しかし、何らかの理由でフィンガープリントが一致しない場合、このようなエラーが表示されます。

    解決策

    この問題の解決策は、ssh-keygenコマンドを用いて、known_hostsファイルからGitHubのエントリを削除することです。以下のコマンドを実行します。

    ssh-keygen -R github.com

    すると、以下のようなメッセージが表示されます。

    # Host github.com found: line 50
    /Users/sumito.tsukada/.ssh/known_hosts updated.
    Original contents retained as /Users/sumito.tsukada/.ssh/known_hosts.old

    このメッセージは、known_hostsファイルからGitHubのエントリが見つかり、 削除されたことを示しています。 また、元のknown_hostsファイルの内容はknown_hosts.oldとして保存されます。 これで問題は解決し、再度GitHubに接続すると新たに公開鍵のフィンガープリントを確認するプロンプトが表示されます。 ここでyesを選択すると、新しいフィンガープリントがknown_hostsファイルに追加され、再度接続する際にはこのフィンガープリントが使用されます。

    まとめ

    今回はGitHubへのSSH接続時に遭遇したエラーとその解決策について説明しました。 この問題は、SSHのフィンガープリント検証がうまくいかない場合に発生します。 解決策はssh-keygen -Rコマンドを用いてknown_hostsから該当のエントリを削除し、再度接続することで新たなフィンガープリントを取得することです。