2024年4月8日月曜日

fastapi にリクエストIDを自動で埋め込む方法 (RequestIdPlugin編)

fastapi にリクエストIDを自動で埋め込む方法 (RequestIdPlugin編)

概要

starlette には RequestIdPlugin という仕組みがありこれを使うと context 経由でリクエストIDを取得できます
アプリコンテキスト配下であれば同一のリクエストIDが取得できるのでロギングなどに使えます

環境

  • macOS 11.7.10
  • Python 3.11.6
    • fastapi 0.110.1
    • starlette 0.37.2
    • starlette-context 0.3.6

サンプルコード

from fastapi import FastAPI
from pydantic import BaseModel
from pydantic_settings import BaseSettings
from starlette.middleware import Middleware
from starlette_context import context
from starlette_context.middleware import RawContextMiddleware
from starlette_context.plugins.correlation_id import CorrelationIdPlugin
from starlette_context.plugins.request_id import RequestIdPlugin

# ミドルウェア定義
# これを定義することで context にリクエスト ID が自動で保持される
middleware = [
    Middleware(RawContextMiddleware, plugins=(RequestIdPlugin(), CorrelationIdPlugin()))
]
# ミドルウェア追加
app = FastAPI(middleware=middleware)


class Settings(BaseSettings):
    message: str = ""


settings = Settings()


class Item(BaseModel):
    message: str


@app.get("/")
async def get_msg():
    # コンテキスト情報からリクエストIDの取得
    return {
        "message": settings.message,
        "context": context,
    }


@app.post("/")
def set_msg(item: Item):
    settings.message = item.message
    return {"message": item.message}

最後に

RequestIdPlugin を使って fastapi にリクエストIDを自動生成する方法を紹介しました
context を使うのでアプリコンテキスト配下のモジュール出ないと参照できないのでそこは注意しましょう

参考サイト

2024年4月5日金曜日

Python で Slack API をコールする

Python で Slack API をコールする

概要

python-slack-sdkを使ってチャネルにメッセージをポストする方法を紹介します

環境

  • macOS 11.7.10
  • Python 3.11.6
    • slack_sdk 3.27.1
  • Slack 2024/04/05 時点の画面

Slack アプリの作成

https://api.slack.com/tutorials/tracks/getting-a-token このあたりから作成すると良いです
アプリをワークスペースにも追加しましょう

Bot トークン

Slack にはトークンの種類がいくつかあり今回は Bot トークンを使います

アプリの左メニューから「Install App」を選択し「Bot User OAuth Token」を使います

URL で言うと https://api.slack.com/apps/xxxxxxx/install-on-team? という形式になります

インストール

  • pipenv install slack_sdk

サンプルコード

先ほど取得した Bot トークンを使用します
サンプルコードは指定したチャネルにメッセージをポストするサンプルで Github にあるサンプルスクリプトをそのまま利用します

from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

client = WebClient(token="xoxb-xxxxxxxxxxxxxxxxx")

try:
    response = client.chat_postMessage(channel='#private', text="Hello world!")
    assert response["message"]["text"] == "Hello world!"
except SlackApiError as e:
    # You will get a SlackApiError if "ok" is False
    assert e.response["ok"] is False
    assert e.response["error"]  # str like 'invalid_auth', 'channel_not_found'
    print(f"Got an error: {e.response['error']}")
    # Also receive a corresponding status_code
    assert isinstance(e.response.status_code, int)
    print(f"Received a response status_code: {e.response.status_code}")

チャネルの内容を取得する

ついでにチャネルに流れるメッセージを取得するスクリプトも動かしてみました
トークンは先ほど取得した Bot トークンを使用します

直近100件のメッセージを取得します

ちなみに RTM API は非推奨になっています (参考)
なので今回は conversations.history を使っています

from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

client = WebClient(token="xoxb-xxxxxxxxxxxxxxxxx")

conversation_history = []
channel_id = "C0123456789"

try:
    result = client.conversations_history(channel=channel_id)
    conversation_history = result["messages"]
    print("{} messages found in {}".format(len(conversation_history), channel_id))
    for msg in conversation_history:
        print(msg["text"])

except SlackApiError as e:
    print("Error creating conversation: {}".format(e))

channel_id はアプリでチャネル名を右クリックし Copy link で取得できます
またボットがチャネルに参加していないと会話は取得できないのでボットを招待してあげましょう (すでにメッセージを送信しているとチャネルに参加しているように見えますがまだいないのでちゃんと /invite してあげましょう)

最後に

Python で Slack のAPI をコールする方法を紹介しました
Slack には 3 つのトークン (User トークン、Bot トークン、アプリレベルトークン) があり今回のようにスクリプトベースの場合には Bot トークンを使います

RTM API が非推奨になり Socket API を変わりに使うようになったようなので機会があれば試してみたいです

参考サイト

2024年4月3日水曜日

pyright で dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.73.dylib

pyright で dyld: Library not loaded: usr local opt icu4c lib libicui18n.73.dylib

概要

Mac 上の pyright でタイトルのエラーが出たので対応しました

環境

  • Python 3.11.6
  • pyright 1.1.356
  • macOS 11.7.10

対応方法

  • brew reinstall node

To retry an incomplete download, remove the file above.

上位の reinstall 中に xz でエラーが発生したので対応しました

エラー文のその上に表示されているキャッシュファイルを削除する

ex)

  • rm /Users/kakakikikeke/Library/Caches/Homebrew/downloads/9a5d194e1a978ebb3dac37f12deaa4085d4d1016cb31bcbf54b7a60103c3e1e6--xz-5.6.1.tar.gz

そして再度 install する

  • brew update
  • brew reinstall xz

最後に

pyright は node なので node まわりのインストールを見直すと良いでしょう
スペックの低いマシンだと node reinstall にかなり時間がかかります (自分の場合1時間以上かかりました

2024年4月2日火曜日

alpine の最新版で venv を作成した場合に python スクリプトを実行する方法

alpine の最新版で venv を作成した場合に python スクリプトを実行する方法

概要

過去に alpine で venv を作成し pip install する方法を紹介しました
今回は python スクリプトを実行する方法を紹介します

環境

  • Ubuntu 22.04
  • docker 25.0.2
  • lego 4.16.1

dockerfile

docker ファイル内では boto3 をインストールします
このイメージ内で boto3 を import できるようにします

FROM goacme/lego:v4.16.1

RUN apk update
RUN apk add --no-cache --virtual .build-deps python3-dev python3 py3-pip
RUN python3 -m venv ~/test_venv --system-site-packages
RUN ~/test_venv/bin/pip3 install --upgrade pip setuptools
RUN ~/test_venv/bin/pip3 install boto3

python スクリプト

boto3 を import することをテストするスクリプトです
これを先程ビルドしたイメージ内で実行します

import boto3

print("Succeed to import boto3")

起動

ポイントは python3 の実行コマンドのパスです
作成した venv 内にある python3 を使うのがポイントです
また lego の場合ホームディレクトリは /root になっているのでそこに配置していますがスクリプトの配置先はどこでも OK です

  • docker run --rm --entrypoint "" -v $(pwd)/test.py:/root/test.py test /root/test_venv/bin/python3 /root/test.py

最後に

alpine の最新版で python スクリプトを実行する方法を紹介しました
ポイントは venv にインストールした python3 を使う点です

2024年4月1日月曜日

The system-wide python installation should be maintained using the system package manager (apk) only. 対応

The system-wide python installation should be maintained using the system package manager (apk) only. 対応

概要

古い alpine では virtualenv を作成しないと pip install ができないようなので対応策を紹介します

環境

  • Ubuntu 22.04
  • docker 25.0.2
  • lego 4.16.1

対応前 dockerfile

FROM goacme/lego:v4.16.1

RUN apk update
RUN apk add --no-cache --virtual .build-deps python3-dev python3 py3-pip
RUN pip3 install --upgrade pip setuptools
RUN pip3 install awscli
RUN aws configure list

これだと3つ目の RUN のpip3 install でエラーになります

対応版 dockerfile

FROM goacme/lego:v4.16.1

RUN apk update
RUN apk add --no-cache --virtual .build-deps python3-dev python3 py3-pip
RUN python3 -m venv ~/test_venv --system-site-packages
RUN ~/test_venv/bin/pip3 install --upgrade pip setuptools
RUN ~/test_venv/bin/pip3 install awscli
RUN ~/test_venv/bin/aws configure list

一度 venv を作成しそこにインストールされるコマンドを使うことでエラーにならなくなります

active しても OK です

最後に

エラーに記載されている通りに venv を作成するのが一番かなと思います
また alpine のバージョンを下げることで対応もできますが基本は新しいバージョンを使ったほうがいいのでおすすめはしません

参考サイト

2024年3月31日日曜日

iOS アプリを久しぶりにビルドしたときのメモ

iOS アプリを久しぶりにビルドしたときのメモ

概要

最終ビルドは 2021/7 頃のアプリになります
もともと Swift5 化はしていたプロジェクトになります

環境

  • Xcode 15.3
  • macOS 14.4.1

libarclite 対応

エラー

SDK does not contain 'libarclite' at the path '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a'; try increasing the minimum deployment target

対処方法

cocoapods などでインストールしたライブラリに対して行います
iOS Deployment Target を 12 以上にします
あまりメンテナンスされていないライブラリや古いライブラリの場合に発生します

  • Pods -> Project-> Build Settings -> iOS Deployment Target -> 12.0

ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES を inherited にする

エラー

cocoapods で表示される警告になります

[!] The `projectUITests [Debug]` target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `Pods/Target Support Files/Pods-project-projectUITests/Pods-project-projectUITests.debug.xcconfig'. This can lead to problems with the CocoaPods installation

対処方法

ビルド設定で ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES を $(inherited) を設定します

  • Target -> projectTests -> Build Settings -> Always Embed Swift Starndard Libraries -> $(inherited)

Sandbox オプションの無効化

エラー

データ保存系のライブラリで発生している気がします

Sandbox: rsync.samba(19313) deny(1) file-read-data /Users/user/Library/Developer/Xcode/DerivedData/project-bpovlgogrctpyxcxspcdgxydcxon/Build/Products/Debug-iphonesimulator/XCFrameworkIntermediates/Realm/Headers

対処方法

  • Project-> Build Settings -> User Script Sandboxing -> No

各種非推奨のコードなどの変更

Xcode が指摘してくれるおすすめ設定やコードリファクタを行いましょう

古いライブラリや存在していないライブラリの削除

例えば Firebase/AdMob はすでに存在していません
存在していないのですがなぜか使えて使っている場合は古い Firebase/Core が使われてしまうので危険です
ちゃんと代替の Google-Mobile-Ads-SDK を使う必要があります

+  pod 'Google-Mobile-Ads-SDK'
-  pod 'Firebase/AdMob'

最後に

定期的にビルドするのが大事です

2024年3月28日木曜日

Kindle for Mac はシステム側の言語が英語になっている場合に Amazon.com に接続してしまう

Kindle for Mac はシステム側の言語が英語になっている場合に Amazon.com に接続してしまう

概要

その場合の対象方法を紹介します

環境

  • macOS 14.4
  • Amazon Kindle 7.4

対処方法

System Settings -> Language & Region の Applications に Kindle アプリを追加する

Kindle アプリから一度ログアウトし再起動する

するとちゃんとログイン画面も日本語になり接続先も Amazon.co.jp になります
ログインするとスマホ側の Kindle や SMS でログイン通知が来ると思います

最後に

システム側のデフォルト言語を英語にしている場合は Amazon.com に接続に行ってしまうようなので注意しましょう

携帯番号の設定やメールアドレスを co.jp と .com で分ける方法もあるようですが一番てっとり早いのは Language & Region を使う方法かなと思います

参考サイト