7rikazhexde’s tech log

技術的な興味関心、備忘録、アウトプットなどを書いています。

【Obsidian】テンプレート設定とショートカットキーの使い方

概要

私はメモアプリとしてObsidianを使用しています。

ノート作成時は右クリック > insertで、Tableなどを挿入できますが、調べると設定から作成済みのテンプレートを指定して挿入できることがわかりました。

本記事ではObsidianのテンプレート機能について以下内容について記載します。

  • テンプレートの設定(Core plugins / Templates)
  • ショートカットキーの設定とテンプレートの挿入(Options / Hotkeys)
  • 新規ノート作成時にテンプレート呼び出し可能なプラグインである Auto Template Trigger の設定

テンプレートの設定(Core plugins / Templates)

以下でテンプレート保存先を指定します。

Settings > Core plugins > template folder location

下記例ではTemplatesとしています。

Obsidian_Core-plugins_Templates設定

ショートカットキーの設定とテンプレートの挿入(Options / Hotkeys)

以下で挿入します。

command + p > Templates: insert template > 挿入したい作成したテンプレートを選択する

これで作成したテンプレートを選択することでノートに挿入することができます。

追加情報として、私は検索が操作が手間だと感じたため、Templates: insert templateを呼び出せるように、hotkeyを設定して、すぐに選択できるようにしました。

Settings > Options > Hotkeys

Templates: insert templateで検索し右側の+ボタンで、割り当てたいキーを入力して設定します。

割り当ては自由ですが、下記例では、option + iとしています。

Obsidian_Options_Hotkeys_Template設定

新規ノート作成時にテンプレート呼び出し可能なプラグインである Auto Template Trigger の設定

他にもファイル作成時にテンプレートを選択することも可能です。

Community pluginである、Auto Template Triggerを使用します。

Community plagins > Brows > Auto Template Trigger

注意点として、事前に上記記載のtemplate folder locationを設定する必要があるので未設定の場合は設定が必要です。

これで新規ノート作成時にTemplates: insert templateを起動してくれます。

まとめ

本記事ではObsidianのテンプレート機能について以下内容について記載しました。

  • テンプレートの設定(Core plagins / Templates)
  • ショートカットキーの設定とテンプレートの挿入(Options / Hotkeys)
  • 新規ノート作成時にテンプレート呼び出し可能なプラグインである Auto Template Trigger の設定

また便利な機能があれば記事で紹介したいと思います。

最後に、記事が参考になれば、是非「はてなスター」もお願いします!

以上です。

2023年振り返り

2023年を振り返ると

今年は何をしただろうと振り返ると、ChatGPTを活用することでよりコードを書くことが増えた一年だったかなという印象でした。

関連してブログ記事も作成したコード関連の記事投稿が多かったかなと思います。

他にもSSGであるMaterial for MkDocsを使用して技術系のまとめサイト作成しました。こちらは全然アクセスはないですが、備忘録として自分がわかれば良いと思っているので、悲観的ではありません。また、サイトは将来的には他のSSGに移行する可能性はありますが、今はMkDocsで満足しています。

7rikazhexde.github.io

ブログに関しては月1本以上の記事を書こうと決めてから継続しています。今年はGA4を設定したのですが、環境構築系の記事へのアクセスが多い印象でした。一方で作成したプロジェクトに関する記事へのアクセスは少ないので残念な気持ちがあります。(それ程記事があるわけではなく、アクセスもゼロではないですが。)

作成したコード(GitHub)では主にPythonですが、pre-commit、GitHub Actionなど、CI/CD環境を作成して運用することも試しました。また、issueの登録、プルリクエスト、リリースなど基本的な操作も実際に使って確認しました。他にもdockerやクラウド(AWS)もアカウント作成して試しました。

まだまだやりたいことだったり、身につけたいスキルはあります。とりあえず触って作って使ってみることを意識していましたが、今後もこの意識は変えずに取り組んでいこうと思います。

仕事の話について

仕事は組み込み系がメインで要求分析からシステム評価が主業務ですが、本業とは別にAI,クラウド関連の業務をやったり、忙しい中でもやりたいことはやったかなという1年でした。

その他、外部の技術系コンサル関連の研修に参加して、要求から設計までのスキル強化ができたと感じでいます。

研修ではアーキテクトの育成強化、つまり設計力強化が目的で、ベテラン社員に成果物をレビューして、フィードバックを受けて、成果物を提出するというプロセスがありました。成果物では担当プロジェクトに関して、要求分析、目的、設計方針、モデル化(静的/動的構造)、目的に対する考察、という流れでした。対象プロジェクトに依存しますが、基本的にはアーキテクチャ変更とリファクタリングになります。12月末時点では成果物は提出済みであり、認定結果待ちですが、無事に認定されれば良いなと思ってます。

また、本業は組み込みと言いましたが、弊社にも当てはまる話として、23年末時点でダイハツの不正が大きな問題になってますが、弊社もリストラ、開発期間短縮、同時開発など、一部共通する部分もあり、トラブルが多発した状況がありました。ダイハツのアンケート調査結果を見ると、既視感を感じることがありました。(ダイハツより風通しは良い気はしますが、そんなに商品作る意味あるのか?と疑問に思うことはありました。)

弊社ではトラブルに関して、上層部が問題を分析して、企画書や販売後のフィードバック、営業とのコミュニケーション、売上比率は低い商品の開発停止、開発期間を遅らせる、外部評価機関に評価依頼、UTの強化など、対策が取られることになりました。

弊社は車ほど人命に関わる物ではないとは言え、強引に進めること(そうせざる得ない状況ではあった)は、個人的には良い方向に行くことはないと思います。真意はわかりませんが、トヨタも言わせない雰囲気があり、ダイハツも言えない雰囲気を作ってしまったのかなと。プロセスは成功するとそれが標準になりますが、標準にすることに対する議論が足りなかったのでは?体制に大いに問題があったのかなと思います。時代に合わないプロセスとかたくさんあったのかなとも。

第三者委員会による調査結果および今後の対応について|ニュースリリース|ダイハツ工業株式会社 企業情報サイト

第三者委員会 調査報告書

個人的な話

少し話が変わりますが、仕事でそんな状況が続く中で、私は4月以降、耳の調子が悪くなり、夜寝れない状況にありました。体調の波はありますが、現在も錠剤を飲んで過ごしています。一時調子が良くなったときもありましたが、仕事のストレスも一因と考えており、通院、薬を飲みながら様子を見ています。(早く回復したいところです。)

一方、来年で今の業界で10年目という節目もあり、転職も意識しています。個人的に興味関心がある企業についてはイベントに参加して調べていますが、転職サイト(エンジニアHub、Findy)を登録して調べてもいます。(エンジニアHubはサービス終了するようなので他のサービスを検討しようと思ってます。)

どうも体の調子がパッとしない部分があるので、どこか踏み込めない部分はありますが、一歩踏み出さなければ何も進まないので、来年は具体的にアクションを起こしたいと考えています。

25年に向けて

まずは健康でありたい。次にスキル獲得。スキルについては、特にワークフロー、クラウド、データ分析を計画的に学習したいなという思いがあります。あとはRustにすごく興味を持っているので、学習して何か作ってみたいなと考えています。(まずはRust本を読む。)

また、情報として、Findyのサービスである2023年末時点のGitHubのコントリビューションの集計結果と偏差値を載せておきます。コントリビューションは多からず、少なからずという感じでした。基本土日メインなのでこの程度かなという感じです。偏差値は60が壁と聞くので、Pythonはあと少しですが、60を目指したいと思います。(何をしたら数値が上がるのかはわかっていないのですが)

Findy_GitHub_2023年_年間コントリビューション

Findy_GitHub_2023年_スキル偏差値

会社ではAzure OpenAI ServiceでGPTを使えるようになり、udemy bussinessも契約されたので、積極的に活用していきスキル強化に繋げたいと思いますし、資格も取りたいと考えています。(直近ではG検定止まりです。)

あと、個人でやったことを振り返ることとして、月次の投稿もしていきないなと考えています。 下記のX(Twitter)で投稿を見ていただくと分かると思いますが、その月で「何をやったかをまとめてなくて結局書けなかった。」ということがあったの、気軽に日記を書くことを目的にしたShortcutsを使って月次の投稿もしていきます。Shortcutsは公開する予定ですので、気になれば使ってもらえると嬉しいです。(別途ブログで公開予定です。)

色々やりたいことがあります。どれも中途半端にならないように注意して、24年は仕事とプライベートのバランスを取りながら、健康にも注意して過ごせるようにしていきたいと思います。

まとまりのない文章になってしまった気もしますが、内容は以上となります。
最後まで読んでいただきありがとうございました。

既存のPoetry環境をベースにしたDocker環境の構築方法について

はじめに

Docker上でPoetryの依存ファイルを使用した環境を構築したいと思い調査しました。
本記事はその手順の備忘録となります。

使用するプロジェクト

以下のプロジェクトを例に説明します。 詳細は割愛しますが、pythonでdashフレームワークを使用したwebアプリのプロジェクトになります。現状はpoetryコマンドで実行環境を構築できるようにしていますが、これをdocker環境でも構築できるようにします。

github.com

方針

作業ディレクトリにプロジェクトと同じフォルダ(dlSubscanStakingRewardsHistoryDash)を構築します。
そして、Docker環境ではアプリケーションの実行で必要となる後述するソースコード類(パッケージ管理ファイルも含む)が格納されたフォルダ、および、ファイルをコピーして同期することにします。

フォルダ構成

ソースコードapp,ci,testフォルダに格納されています。
メインのプログラムはappフォルダ内のコードで、プロジェクト以下でpoetry run python appを実行することでDashフレームワークのWebアプリが起動します。

# 以下は一部記載を省略しています。
% tree -a -L 2
.
├── .DS_Store
├── .demofile
├── .git
├── .gitignore
├── .markdownlint.jsonc
├── .mypy_cache
├── .pre-commit-config.yaml
├── .ruff_cache
├── .venv
├── .vscode
├── Dockerfile
├── LICENSE
├── README.md
├── app
│   ├── __init__.py
│   ├── __main__.py
│   ├── __pycache__
│   ├── assets
│   ├── config.toml
│   ├── config_manage.py
│   ├── cryptact.py
│   ├── dcc_manage.py
│   ├── df_manage.py
│   └── subscan.py
├── ci
│   ├── run_git_tag_base_pyproject.py
│   └── update_pyproject_version.py
├── docker-compose.yaml
├── poetry.lock
├── pyproject.toml
├── requirements-dev.txt
├── requirements.txt
├── scripts
│   └── create_post-commit.sh
└── tests
    ├── __init__.py
    └── test_cryptact.py

続けて方針に従いDockerfiledocker-compose.yamlを作成します。

Dockerfile

# ベースとなるDockerイメージを指定
FROM python:3.10

# 作業ディレクトリを設定
WORKDIR /

# APTパッケージインストール / パッケージアーカイブのキャッシュ削除 / パッケージリストのキャッシュ削除
# 日本語のロケールを指定
RUN apt-get update && \
    apt-get -y --no-install-recommends install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9

# ターミナルエミュレーターにxtermを指定する
ENV TERM xterm

# Poetryのインストール
## https://python-poetry.org/docs/#installing-with-the-official-installer
### Linux, macOS, Windows (WSL)
RUN curl -sSL https://install.python-poetry.org | python3 -

# Poetryのパスをunix指定で設定
## https://python-poetry.org/docs/#installing-with-the-official-installer
### Add Poetry to your PATH
ENV PATH /root/.local/bin:$PATH

# Poetryが仮想環境を生成しないようにする
RUN poetry config virtualenvs.create false

# 作業ディレクトリを/dlSubscanStakingRewardsHistoryDashに設定
WORKDIR /dlSubscanStakingRewardsHistoryDash

# 依存関係のコピー
COPY pyproject.toml poetry.lock ./

# 依存関係のインストール
RUN poetry install

# アプリケーションのコピー
COPY ./app ./app
COPY ./tests ./tests
COPY ./ci ./ci
COPY README.md .

補足: Dockerfile用のlinterについて

pre-commitではpre-commit hookとして以下のDockerfile linterが公開されています。
Dockerfileの構文や指定について指摘されるため、pre-commitを利用している場合は下記指定で使用できます。 実際に、Dockerfileはフックの結果を元に作成しています。個人的には有用だと感じました。

.pre-commit-config.yaml

  # https://github.com/pryorda/dockerfilelint-precommit-hooks#usage
  - repo: https://github.com/pryorda/dockerfilelint-precommit-hooks
    rev: v0.1.0
    hooks:
      - id: dockerfilelint
        stages: [commit]

docker-compose.yaml

# Docker Composeのバージョン指定
version: '3'
services:
  # アプリケーションサービスの設定
  app:
    # カレントディレクトリをベースにビルド
    build: .
    # コンテナの名前を指定
    container_name: 'dlssrhd'
    # ターミナルの割り当てを有効にする
    tty: true
    # ボリュームのマウント設定
    volumes:
      - ./app:/dlSubscanStakingRewardsHistoryDash/app
      - ./tests:/dlSubscanStakingRewardsHistoryDash/tests
      - ./ci:/dlSubscanStakingRewardsHistoryDash/ci
      - ./pyproject.toml:/dlSubscanStakingRewardsHistoryDash/pyproject.toml
      - ./poetry.lock:/dlSubscanStakingRewardsHistoryDash/poetry.lock
      - ./README.md:/dlSubscanStakingRewardsHistoryDash/README.md
    # ポートのマッピング
    ports:
      - 8050:8050
    # アプリケーションの起動コマンド実行
    command: ["poetry", "run", "python", "app"]

補足: docker compose ファイルが有効かどうかをチェックするpre-commit

pre-commitではpre-commit hookとして以下のdocker-pre-commitが公開されています。
docker-compose configコマンドを使用して、作成したdocker-compose.yamlについて環境変数の評価や、ファイルのインクルードなど、Composeファイルが正しく構成されているかどうかを確認するとができます。pre-commitを利用している場合は下記指定で使用できます。 実際に、docker-compose.yamlに適用し、指摘はありませんでしたが、docker-compose configをpre-commitで実行できるので有用だと思います。

.pre-commit-config.yaml

  # https://github.com/IamTheFij/docker-pre-commit#installation
  - repo: https://github.com/iamthefij/docker-pre-commit
    rev: v3.0.1
    hooks:
      - id: docker-compose-check

Docker環境の構築

docker-compose upappサービスのdlssrhdコンテナを起動する

処理の流れ

  1. docker-compose upコマンド実行:

    • docker-compose upコマンドを実行すると、Docker Composeは指定されたdocker-compose.yamlを読み込みます。
  2. ベースとなるDockerイメージのダウンロード:

    • python:3.10というベースイメージがなければ、このイメージをDocker Hubからダウンロードします。
  3. Dockerfileのビルド:

    • ダウンロードしたベースイメージを元に、指定されたDockerfileがビルドされます。
    • ビルドの際には、各命令が順番に実行されます。
  4. 作業ディレクトリとロケールの設定:

  5. Poetryのインストール:

  6. Poetryのパスの設定:

    • インストールしたPoetryのパスを環境変数に追加します。
  7. Poetryの仮想環境生成設定:

    • Poetryが仮想環境を生成しないように設定します。
  8. 作業ディレクトリの変更:

    • 以降の作業は、/dlSubscanStakingRewardsHistoryDashディレクトリで行います。
  9. 依存関係のコピーとインストール:

    • pyproject.tomlpoetry.lockがコピーされ、Poetryを使用して依存関係がインストールされます。
  10. アプリケーションのコピー:

    • ./app./tests./ciREADME.mdがコピーされます。
  11. ポートのバインドとコンテナの起動:

    • docker-compose.yamlで指定されたポート8050がホストマシンのポート8050にバインドされ、dlssrhdという名前のコンテナが起動されます。
  12. Pseudo-TTYの割り当て:

    • tty: trueが指定されているため、コンテナ内で対話的なシェルを使用できるようになります。
  13. docker-compose.yamlのcommandの指定:

    • docker-compose.yamlcommand: ["poetry", "run", "python", "app"]の指定からデフォルトのコンテナ起動時のコマンドとして使用されます。

これにより、docker-compose upコマンドによって、指定されたサービス(appサービス)に基づいたコンテナが構築、起動され、アプリケーションが実行されます。

補足:CMDcommandの使い分け

プロジェクトの運用方針にもよりますが、CMDcommandの両方を使用する場合はdocker-compose.yamlcommandが優先されるようなので、個人的にはcommandでコマンド実行するのが良いと思います。

参考記事

qiita.com

  1. CMDのみを使用する場合:

    • CMD ["poetry", "run", "python", "app"]
      • コンテナが実行されるときに、何もコマンドが指定されなかった場合はCMDで指定されたコマンドが実行されます。
  2. commandのみを使用する場合:

    • command: ["poetry", "run", "python", "app"]
      • docker-compose.yamlcommandでコンテナの起動時のコマンドを上書きします。
      • CMDにコマンドの指定がある場合でも、docker-compose.yamlcommandで指定したコマンドが優先されます。
  3. CMDとcommandの両方を使用する場合:

    • CMD ["poetry", "run", "python", "app"]
    • command: ["poetry", "run", "python", "app"]
      • この場合、docker-compose.yamlcommandが優先されます。

補足:コンテナの起動方法

参考記事

qiita.com

コンテナ一覧を表示

% docker ps -a                
CONTAINER ID   IMAGE                                    COMMAND                   CREATED       STATUS                      PORTS                    NAMES
5c41a6c6a8ca   dlsubscanstakingrewardshistorydash-app   "poetry run python a…"   5 hours ago   Up 22 seconds               0.0.0.0:8050->8050/tcp   dlssrhd

単一コンテナ起動: docker start "CONTAINER ID"

 % docker start 5c41a6c6a8ca           

5c41a6c6a8ca

複数コンテナ(アプリケーション)の起動: docker compose up

appサービスのdlssrhdコンテナを起動する

% docker compose up
[+] Building 0.0s (0/0)                                                                                        docker:desktop-linux
[+] Running 1/0
 ✔ Container dlssrhd  Created                                                                                                  0.0s 
Attaching to dlssrhd
dlssrhd  | Skipping virtualenv creation, as specified in config file.
dlssrhd  | Dash is running on http://0.0.0.0:8050/
dlssrhd  | 
dlssrhd  |  * Serving Flask app '__main__'
dlssrhd  |  * Debug mode: on

# Ctrl+Cで停止
^CGracefully stopping... (press Ctrl+C again to force)
Aborting on container exit...
[+] Stopping 1/1
 ✔ Container dlssrhd  Stopped                                                                                                  0.3s 
canceled

# -d(デタッチドモード) でバックグラウンドでサービスを実行
% docker compose up -d     
[+] Building 0.0s (0/0)                                                                                        docker:desktop-linux
[+] Running 1/1
 ✔ Container dlssrhd  Started 

まとめ

実際のプロジェクトを例にPoetryを使用したDocker環境の構築方法について紹介しました。

環境構築について、プロジェクトではフォルダ構成を維持して、全てのファイルをコピーせず、必要なファイルをコピーしたかったので、実際に作成することで処理の流れを理解することができました。

Docker環境のインストールは必要ですが、実際にMacWindows(WSL)でgitクローンしてdocker-compose upコマンドを実行してwebアプリを起動できることを確認できました。

今後や他のプログラミング言語やDBと組み合わせたサービスについても、調査して作成してみたいと思います。

以上です。

「Warning: poetry-plugin-export will not be installed by default in a future version of Poetry.」の対応について

要約

  • pre-commitのpoetry-export hookで警告が表示された
  • poetry-plugin-exportをインストールする
  • poetry self show pluginsでインストール内容を確認し、 poetry config warnings.export falseで警告表示を無効にする

現象

pre-commitでpoetry-export hookを使用しているのですが、v1.7.1に変更し、poetry run pre-commit run --all-filesを実行したところ、以下の警告が表示されました。

Warning: poetry-plugin-export will not be installed by default in a future version of Poetry. In order to avoid a breaking change and make your automation forward-compatible, please install poetry-plugin-export explicitly. See https://python-poetry.org/docs/plugins/#using-plugins for details on how to install a plugin. To disable this warning run 'poetry config warnings.export false'.

公式ドキュメントにも同様の警告内容が記載されていました。

python-poetry.org

実行環境

.pre-commit-config.yaml(poetry部分抜粋)

  # https://python-poetry.org/docs/pre-commit-hooks/#usage
  - repo: https://github.com/python-poetry/poetry
    # Cannot be executed with local designation (as of 23.11.25)
    rev: 1.7.1
    hooks:
      - id: poetry-check
        verbose: true
      - id: poetry-lock
        verbose: true
      - id: poetry-export
        args: ["-f", "requirements.txt", "-o", "requirements.txt"]
        verbose: true
        files: ^pyproject\.toml$
      - id: poetry-export
        args: ["--dev", "-f", "requirements.txt", "-o", "requirements-dev.txt"]
        verbose: true
        files: ^pyproject\.toml$

解決方法

警告メッセージの記載通りですが、将来のPoetryのバージョンでは、poetry-plugin-exportはデフォルトではインストールされないようです。したがって、自動化が前方互換性を持つように、poetry-plugin-exportを明示的にインストールすることが推奨されます。そこで、公式のインストール手順を確認し、poetry-plugin-exportをインストールします。

github.com

poetry self add poetry-plugin-export

Using version ^1.6.0 for poetry-plugin-export

Updating dependencies
Resolving dependencies... (0.2s)

No dependencies to install or update

Writing lock file

念の為以下のコマンドでインストールされたプラグインを確認します。

poetry self show plugins                   

  • poetry-plugin-export (1.6.0) Poetry plugin to export the dependencies to various formats
      1 application plugin

      Dependencies
        - poetry (>=1.6.0,<2.0.0)
        - poetry-core (>=1.7.0,<2.0.0)

動作確認

poetry run pre-commit run --all-filesによる確認

poetry run pre-commit run --all-files
# 省略

poetry-export............................................................Passed
- hook id: poetry-export
- duration: 0.69s

Warning: poetry-plugin-export will not be installed by default in a future version of Poetry.
In order to avoid a breaking change and make your automation forward-compatible, please install poetry-plugin-export explicitly. See https://python-poetry.org/docs/plugins/#using-plugins for details on how to install a plugin.
To disable this warning run 'poetry config warnings.export false'.

poetry-export............................................................Passed
- hook id: poetry-export
- duration: 0.7s

Warning: poetry-plugin-export will not be installed by default in a future version of Poetry.
In order to avoid a breaking change and make your automation forward-compatible, please install poetry-plugin-export explicitly. See https://python-poetry.org/docs/plugins/#using-plugins for details on how to install a plugin.
To disable this warning run 'poetry config warnings.export false'.
The `--dev` option is deprecated, use the `--with dev` notation instead.

poetry exportによる確認

poetry export -f requirements.txt --output requirements.txt
Warning: poetry-plugin-export will not be installed by default in a future version of Poetry.
In order to avoid a breaking change and make your automation forward-compatible, please install poetry-plugin-export explicitly. See https://python-poetry.org/docs/plugins/#using-plugins for details on how to install a plugin.
To disable this warning run 'poetry config warnings.export false'.

コマンドの実行結果から、poetry exportコマンドを実行しても警告メッセージは表示され続けます。プラグインはインストールされたことは確認しているので、poetry config warnings.export falseで警告表示を無効にします。

poetry config warnings.export false

警告メッセージ表示を無効にしているので、正しく設定できているが不安になりますが、これで警告表示は消えて引き続きpoetry exportフックが使用できるはずです。

以上です。

【AWS】API Gateway + Lambda + DynamoDB構成でGETリクエストで DBのデータ(json)を取得して、 DataFrameを作成する

前書き

これまでは私はクラウド(AWS)と通信するデバイス側の開発(組込みデバイス、デスクトップアプリ)が中心でした。I/Fの仕様が決まれば通信はできますが、サービスを作る上でクラウド側の知識がないとエンジニアとして面白みがないなと感じることが増えてきました。これは現業が類似した業務の繰り返しでエンジニアとしてこのままで良いのかという危機感的な部分もありますが、スキルを増やしたいというモチベーションが強いです。

個人的な経験からクラウドの運用にはコストはかかりますが、アイデアを具現化することに関して、短期的に拡張性を考慮して実現することに利点があると考えています。何だかんだ見栄えも良いです。また、その中心はクラウドという印象です。いくらデバイスが良くても、データを取得、分析、解析までできなければ、使えるサービスにはなりません。各工程のスキルを身に付けることは簡単なことではありませんが、作りたいものの選択肢は拡がると思います。

一方で、ちょうど業務でAWSのサービスを使うことになり、良い機会なので、プライベートでもアカウントも作成して触りながら知識を深めていこうと思い、コードを書いてAWSのサービスを使ってみることにしました。

前置きが長くなりましたが、本記事はクラウドを触ってみた記事であり、AWSのサービスとして、API Gateway, Lambda, DynamoDBを使用した記事になります。

前提条件

  • AWSアカウント(ルートユーザー)を作成済みであること

ソースコード

ソースコードGitHubにコミットしています。

github.com

IAMユーザー作成

ルートユーザーでログインし、「IAMユーザーを作成する 」を指定して作成します。

ステップ 1 ユーザーの詳細を指定

  • ユーザー名:[割愛]
  • AWS マネジメントコンソールへのユーザーアクセスを提供する - オプション:チェック
    • IAMユーザーを作成します:選択
    • コンソールパスワード
      • 自動生成されたパスワード
    • ユーザーは次回のサインイン時に新しいパスワードを作成する必要があります - 推奨:チェック

ユーザーは次回のサインイン時に新しいパスワードを作成する必要があります」という項目については、チェックをつけます。 自動作成だと文字数が少ないため、ログイン時に変更した方が良いと思いました。
また、作成後は参照できませんが、作成直後はコピー、csv保存が可能です。

補足: IAMユーザー作成時の選択肢

chatgptより引用(2023/11/05時点)

AWSのIAMユーザー作成時には、以下の2つの選択肢があります。

  1. Identity Centerでユーザーを指定する - Identity Centerでは、AWSアカウントおよびクラウドアプリケーションへのユーザーアクセスを一元管理できます。これは推奨される方法です。
  2. IAMユーザーを作成する - アクセスキー、AWS CodeCommit または Amazon Keyspaces のサービス固有の認証情報、または緊急アカウントアクセス用のバックアップ認証情報を使用してプログラムによるアクセスを有効にする必要がある場合のみ、IAMユーザーの作成が推奨されます。

一般的には、Identity Centerでユーザーを指定することが推奨されています。これにより、AWSアカウントおよびクラウドアプリケーションへのユーザーアクセスを一元管理できます。ただし、プログラムによるアクセスを有効にする必要がある場合は、IAMユーザーの作成を選択することもあります。どちらの選択肢を選ぶかは要件によります。

また、「Identity Centerでユーザーを指定する」場合は、AWS Organizationsを有効化する必要があります。AWS Organizationsは、複数のAWSアカウントを一元管理するためのサービスです。これにより、単一の支払い者と一元化されたコスト追跡が可能になり、他のAWSアカウントを作成して招待したり、ポリシーベースのコントロールを適用したりすることができます。

今回は個人利用で複数のAWSアカウントを管理する必要がないため、「IAMユーザーを作成します」で作成しました。

ステップ 2 許可を設定

  • 許可のオプション:ポリシーを直接アタッチする(AdministratorAccessを指定)

ステップ 3 確認して作成

ユーザーの詳細、許可の概要、タグ(オプション)を確認し、問題がなければ、ユーザーの作成を押下する。
タグ(オプション)は必要に応じて設定する。

ステップ 4 パスワードを取得

パスワード情報をコピー、csv保存し、完了

参考記事

IAMユーザーのアクセスキー作成

AWSの各サービスを利用するためにはアクセスキーが必要になります。アカウント作成時はアクセスキーを自動で作成する選択肢もあったかと思いますが、基本的にはIAMユーザー作成後にアクセスキーを作成します。以下の指定で作成します。

IAMユーザー > セキュリティ認証情報 > アクセスキーを作成 > ユーザーケース選択(※) > 次へ

AWS CLI V2で認証情報を設定、コードで参照する方式のため、コマンドラインインターフェース(CLI)を選択しました。

DynamoDB

テーブルの作成

以下で作成します。その他はデフォルトです。

  • テーブル名:TestJsonTable1
  • パーテーションキー:id
  • ソートキー:date

補足:予約語について

ソートキーで指定するdate予約語です。

DynamoDB の予約語 - Amazon DynamoDB

もし、AWSCLIで取得する場合は#をつけて実行する必要があるようです。
今回作成するLambda関数(Python)ではqueryメソッドを使用しますが、書式は変更しなくても取得出来ました。

DynamoDB の式の属性名 - Amazon DynamoDB

データの追加

pythonコードでjsonファイルを読み込み、テーブルに追加します。 エラーにならなければ"Data written to table successfully."が表示されます。

追加したデータはテーブル > 名前 > 項目の検索から確認できます。
例えば、クエリ、id:camera2date:次の値/2023-04-01および2023-04-2で実行すれば条件に応じたデータを表示できます。

テストデータ(test_data.json)を作成するコード

注意点
  • テストデータは正確ではありません。あくまでサンプルです。
  • データとしては特定のカメラで検出したPoseNetの骨格点情報を持つ日時データ(json)を想定しています。本来は検出時間間隔は短いのですが、サンプルのため30分間隔にしています。
  • skeletal_pointsは都合により検出時間で共通としています。
create_json_file.py
import json
import random
from datetime import datetime, timedelta

# 初期データ
skeletal_points = '[{"key_point": "2", "key_points": [{"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}]}, {"key_point": "3", "key_points": [{"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}, {"prob": "83.89", "x": "464", "y": "115"}]}]'
start_time = datetime(2023, 4, 1)
end_time = datetime(2023, 4, 5)
time_step = timedelta(minutes=30)

# 結果を格納するリスト
results = []

# 指定された時間範囲でループ
while start_time <= end_time:
    result = {
        "detected_date_time": start_time.strftime("%Y-%m-%dT%H:%M:%S.000"),
        "date": start_time.strftime("%Y-%m-%dT%H:%M:%S.000"),
        "detected_status": random.choice(["fallen", "normal"]),
        "id": random.choice(["camera1", "camera2"]),
        "skeletal_points": skeletal_points,
        "num_of_people": str(random.randint(0, 5)),
    }
    results.append(result)
    start_time += time_step

# JSONファイルに保存

with open("./incert_files/test_data.json", "w") as f:
    json.dump({"result": results}, f, indent=2)

test_data.jsonを書き込むコード

incert_data_json.py
import json
import boto3

# DynamoDBオブジェクトを取得
dynamodb = boto3.resource(
    "dynamodb",
    endpoint_url="https://dynamodb.ap-northeast-1.amazonaws.com",  # DynamoDBのエンドポイントURL
)

# テーブル名を定義
table_name = "TestJsonTable1"

# テーブルオブジェクトを取得
table = dynamodb.Table(table_name)

file_name = "./incert_files/test_data.json"

# JSONファイルからデータを読み込む
with open(file_name, "r") as f:
    data = json.load(f)

# データをテーブルに書き込む
for item in data["result"]:
    table.put_item(Item=item)

print("Data written to table successfully.")

API Gateway

GETメソッド 経由でLambda関数を実行するため、API GatewayAPIを作成します。

API作成

REST API

  • 新しいAPI
  • API名:TestJsonTable1_API1
  • APIエンドポイント:リージョン

メソッドを作成

  • メソッドタイプ: GET
  • 統合タイプ:Lambda 関数
  • Lambdaプロキシ:オフ
  • Lambda関数:後述するLambda関数のARNを指定

メソッドリクエストの設定

URL クエリ文字列パラメータ

メソッドリクエストを編集 > URL クエリ文字列パラメータ

  • id:必須(True)
  • start_date:必須(False)
  • end_date:必須(False)

統合リクエストの設定

マッピングテンプレート

{
  "id": "$input.params('id')",
  "start_date": "$input.params('start_date')",
  "end_date": "$input.params('end_date')"
}
マッピングテンプレートを設定する理由

URLクエリのみ設定すると以下のエラーになりました。

{'errorMessage': "'id'", 'errorType': 'KeyError', 'requestId': '[割愛]', 'stackTrace': ['  File "/var/task/lambda_function.py", line 17, in lambda_handler\n    id = event[\'id\']\n']}

chatgptで確認(2023/11/05時点)するとGETリクエストで指定したパラメータはLambda関数ではイベントオブジェクトでは参照できないようです。

これはエラーメッセージ'errorMessage': "'id'", 'errorType': 'KeyError'は、Pythonの辞書(この場合はevent)から存在しないキー(この場合は'id')を取得したことによるエラーです。

API Gateway経由でLambda関数を呼び出すとき、API GatewayはHTTPリクエストを特定の形式のイベントオブジェクトに変換します。このイベントオブジェクトは、Lambda関数のeventパラメータとして渡されます。

しかし、このイベントオブジェクトは、直接Lambda関数をテストするときに使用するイベントオブジェクトとは形式が異なる場合があります。そのため、Lambda関数がevent['id']を期待している場合でも、API Gatewayから渡されるイベントオブジェクトには'id'キーが含まれていない可能性があります。

この問題を解決するためには、API Gatewayの統合リクエストのマッピングテンプレートを設定して、HTTPリクエストから適切な形式のイベントオブジェクトを作成する必要があります。具体的には、マッピングテンプレートでHTTPリクエストのクエリパラメータ(この場合はid、start_date、end_date)をイベントオブジェクトの対応するキーにマッピングします。

これにより、Lambda関数はAPI Gatewayから期待する形式のイベントオブジェクトを受け取り、'id'キーを正しく取得できるようになります。

Lambda

GETリクエストのパラメータを元にDynamoDBから取得するクエリを設定、実行するLambda関数を作成します。

関数の作成

アーキテクチャではx86_64arm64を指定できますが、デフォルトで選択されていたx86_64を指定しました。
下記記事を見る限りは、処理速度、コスト面でarm64を選択するのが良さそうです。

参考記事

Lambdaのポリシー変更(追加)

IAM > アクセス管理 > ロール > Lambdaのロール名
dynamodbにアクセスするため、AmazonDynamoDBFullAccessを追加する
デフォルトではCloudWatchのログ出力するAWSLambdaBasicExecutionRoleが設定されている。

レイヤーの追加

pandasを使用するためPython 3.11版のarnを指定して追加します。

参考記事: [AWS]ARNとは?

pandasのarn情報

arnとして以下を指定します。

arn:aws:lambda:ap-northeast-1:336392948345:layer:AWSSDKPandas-Python311:2

参考情報: AWS Lambda Managed Layers — AWS SDK for pandas 3.4.2 documentation

Lambda関数作成

関数 > 関数名 > コード

import boto3
import pandas as pd
from boto3.dynamodb.conditions import Key

def lambda_handler(event, context):
    dynamodb = boto3.resource(
        "dynamodb",
        region_name="ap-northeast-1",  # 東京リージョン
        endpoint_url="https://dynamodb.ap-northeast-1.amazonaws.com",  # DynamoDBのエンドポイントURL
    )
    table = dynamodb.Table('TestJsonTable1')

    # print文を入れるとCloudWatchにログ出力できる
    # print(event) 

    id = event['id']
    start_date = event.get('start_date')
    end_date = event.get('end_date')

    if start_date and end_date:
        response = table.query(
            KeyConditionExpression=Key('id').eq(id) & Key('date').between(start_date, end_date)
        )
    else:
        response = table.query(
            KeyConditionExpression=Key('id').eq(id)
        )

    # 'result'キーでラップして返す
    return {"result": response['Items']}

タイムアウト時間の設定

実行結果次第でタイムアウト時間を伸ばす場合は以下で変更します。
関数 > 関数名 > 設定 > 一般設定 > 編集 > タイムアウト(変更) > 保存
3秒から30秒に変更しました。

テスト

Lambda関数が期待通り動作するかテストデータを使用して動作確認します。
ログから期待通り出力できていればOKです。

イベントJSON

{
  "id": "camera1",
  "start_date": "2023-04-01T00:00:00.000",
  "end_date": "2023-04-05T00:00:00.000"
}

実行結果

{
  "result": [
    {
      "detected_date_time": "2023-04-01T00:00:00.000",
      "date": "2023-04-01T00:00:00.000",
      "detected_status": "normal",
      "id": "camera1",
      "skeletal_points": "[{\"key_point\": \"2\", \"key_points\": [{\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}]}, {\"key_point\": \"3\", \"key_points\": [{\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}]}]",
      "num_of_people": "0"
    },
    ...
    {
      "detected_date_time": "2023-04-05T00:00:00.000",
      "date": "2023-04-05T00:00:00.000",
      "detected_status": "fallen",
      "id": "camera1",
      "skeletal_points": "[{\"key_point\": \"2\", \"key_points\": [{\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}]}, {\"key_point\": \"3\", \"key_points\": [{\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}, {\"prob\": \"83.89\", \"x\": \"464\", \"y\": \"115\"}]}]",
      "num_of_people": "0"
    }
  ]
}

リクエスト関数

ここまでで、DynamoDB,API Gateway, Lambda関数を作成し、設定することができたのでローカル環境からデータを取得できるか確認します。

動作確認用にrequestモジュールを使用してGETリクエストを送信するコードを作成します。受信したjsonデータはpandas / dataframeに変換して保存します。

事前準備

  • ローカルからAWSにアクセスするため、AWS認証情報を環境変数に設定します。詳細はAWSCLIを参照してください。

  • API GatewayではIAM認証を設定しているため、requests-aws4authをインストールしてください。AWS SigV4 による署名付きリクエストを送信できるようにします。

参考記事

request_api.py
import requests
from requests_aws4auth import AWS4Auth
from typing import Optional
import pandas as pd
import boto3

# AWS認証情報取得
session = boto3.Session()
credentials = session.get_credentials()
aws_access_key_id = credentials.access_key
aws_secret_access_key = credentials.secret_key
region_name = session.region_name
# 「API > ステージ > URLを呼び出す 」より参照
api_endpoint = "ステージ込みのエンドポイントを指定する"

# AWS4Authオブジェクトを作成
auth = AWS4Auth(aws_access_key_id, aws_secret_access_key, region_name, "execute-api")

def get_req(
    id: str,
    columns: list,
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
):
    # リクエストを作成
    url = f"{api_endpoint}?id={id}"
    if start_date is not None:
        url += f"&start_date={start_date}"
    if end_date is not None:
        url += f"&end_date={end_date}"
    response = requests.get(url, auth=auth)

    # レスポンスを表示
    data = response.json()

    new_data = [[item[column] for column in columns] for item in data["result"]]

    # new_dataは上記で作成したリスト
    df = pd.DataFrame(new_data, columns=columns)
    return df


if __name__ == "__main__":
    columns = ["id", "date", "detected_status", "num_of_people","skeletal_points"]
    df = get_req("camera1", columns, "2023-04-01", "2023-04-02")
    print(df)
    #df = get_req("camera1", columns)

実行結果

指定範囲(日付)とcolumnsのリストに対応したDataframeオブジェクトを作成できています。

         id                 date detected_status num_of_people                                    skeletal_points
0   camera1  2023-04-01T00:00:00.000          normal             0  [{"key_point": "2", "key_points": [{"prob": "8...
1   camera1  2023-04-01T01:30:00.000          fallen             1  [{"key_point": "2", "key_points": [{"prob": "8...
2   camera1  2023-04-01T02:00:00.000          fallen             2  [{"key_point": "2", "key_points": [{"prob": "8...
3   camera1  2023-04-01T04:00:00.000          fallen             0  [{"key_point": "2", "key_points": [{"prob": "8...
4   camera1  2023-04-01T05:00:00.000          normal             4  [{"key_point": "2", "key_points": [{"prob": "8...
5   camera1  2023-04-01T06:30:00.000          fallen             0  [{"key_point": "2", "key_points": [{"prob": "8...
6   camera1  2023-04-01T08:00:00.000          fallen             0  [{"key_point": "2", "key_points": [{"prob": "8...
7   camera1  2023-04-01T09:30:00.000          fallen             5  [{"key_point": "2", "key_points": [{"prob": "8...
8   camera1  2023-04-01T10:00:00.000          normal             2  [{"key_point": "2", "key_points": [{"prob": "8...
9   camera1  2023-04-01T10:30:00.000          fallen             2  [{"key_point": "2", "key_points": [{"prob": "8...
10  camera1  2023-04-01T11:00:00.000          fallen             3  [{"key_point": "2", "key_points": [{"prob": "8...
11  camera1  2023-04-01T13:30:00.000          normal             3  [{"key_point": "2", "key_points": [{"prob": "8...
12  camera1  2023-04-01T15:00:00.000          normal             3  [{"key_point": "2", "key_points": [{"prob": "8...
13  camera1  2023-04-01T16:00:00.000          normal             1  [{"key_point": "2", "key_points": [{"prob": "8...
14  camera1  2023-04-01T17:00:00.000          fallen             5  [{"key_point": "2", "key_points": [{"prob": "8...
15  camera1  2023-04-01T18:00:00.000          fallen             5  [{"key_point": "2", "key_points": [{"prob": "8...
16  camera1  2023-04-01T19:30:00.000          fallen             4  [{"key_point": "2", "key_points": [{"prob": "8...
17  camera1  2023-04-01T21:00:00.000          fallen             2  [{"key_point": "2", "key_points": [{"prob": "8...
18  camera1  2023-04-01T23:30:00.000          normal             4  [{"key_point": "2", "key_points": [{"prob": "8...

まとめ

API Gateway + Lambda + DynamoDB構成でGETリクエストでDBのデータを取得して、DataFrameを作成する方法について紹介しました。
実際にサービスを使うことで触りの部分は理解できました。ただ、認証やネットワーク設定はわからない点が多いので、今後は本やドキュメントを見ながら理解を深めていきたいと思います。

以上です。

openssl@1.1アンインストール後にpoetryでSSLエラーになる現象と対応について

概要

  • 以下の記事でopenssl@1.1を削除しましたが、その影響でpoetryが使用できなくなりました。

7rikazhexde-techlog.hatenablog.com

  • 可能性として、python3.10系とopenssl@1.1に依存関係があるため、少なくともopenssl@3を使用する場合はpythonのバージョン上げる必要があることがわかりました。
  • そこで、問題の解消のためpoetryを再インストール(アンインストール → インストール)しました。

実行環境

% sw_vers
ProductName:        macOS
ProductVersion:     13.6.1
BuildVersion:       22G313

% brew --version
Homebrew 4.1.17

% poetry --version
Poetry (version 1.6.1)

現象

poetry self updateでエラー

<注意事項>ログは欠けている可能性があります。

%  poetry self update
Traceback (most recent call last):
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py", line 327, in run
    exit_code = self._run(io)
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/application.py", line 190, in _run
    exit_code: int = super()._run(io)
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py", line 378, in _run
    name = self._get_command_name(io)
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py", line 610, in _get_command_name
    if self.has(candidate):
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py", line 232, in has
    self._command_loader.has(name) and self.add(self._command_loader.get(name))
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/loaders/factory_command_loader.py", line 34, in get
    return factory()
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/application.py", line 44, in _load
    module = import_module("poetry.console.commands." + ".".join(words))
  File "$HOME/.pyenv/versions/3.10.4/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/commands/self/update.py", line 8, in <module>
    from poetry.console.commands.add import AddCommand
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/commands/add.py", line 13, in <module>
    from poetry.console.commands.init import InitCommand
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/commands/init.py", line 16, in <module>
    from poetry.utils.dependency_specification import RequirementsParser
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/utils/dependency_specification.py", line 19, in <module>
    from poetry.packages.direct_origin import DirectOrigin
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/packages/direct_origin.py", line 10, in <module>
    from poetry.inspection.info import PackageInfo
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/inspection/info.py", line 26, in <module>
    from poetry.utils.env import EnvCommandError
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/utils/env/__init__.py", line 9, in <module>
    from poetry.utils.env.base_env import Env
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/utils/env/base_env.py", line 15, in <module>
    from virtualenv.seed.wheels.embed import get_embed_wheel
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/__init__.py", line 3, in <module>
    from .run import cli_run, session_via_cli
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/run/__init__.py", line 11, in <module>
    from ..seed.wheels.periodic_update import manual_upgrade
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-

poetry new コマンドでもエラー

どうやらpython 3.10/3.10.4openssl@1.1を使用しているが見つからないのでエラーになっているという状況でした。 これはopenssl@1.1をアンインストールしたことによる影響でした。

% poetry new my_project

Traceback (most recent call last):
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py", line 327, in run
    exit_code = self._run(io)
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/application.py", line 190, in _run
    exit_code: int = super()._run(io)
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py", line 431, in _run
    exit_code = self._run_command(command, io)
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py", line 473, in _run_command
    raise error
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py", line 454, in _run_command
    self._event_dispatcher.dispatch(command_event, COMMAND)
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/events/event_dispatcher.py", line 26, in dispatch
    self._do_dispatch(listeners, event_name, event)
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/events/event_dispatcher.py", line 89, in _do_dispatch
    listener(event, event_name, self)
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/application.py", line 283, in configure_env
    from poetry.console.commands.self.self_command import SelfCommand
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/commands/self/self_command.py", line 13, in <module>
    from poetry.utils.env import EnvManager
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/utils/env/__init__.py", line 9, in <module>
    from poetry.utils.env.base_env import Env
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/utils/env/base_env.py", line 15, in <module>
    from virtualenv.seed.wheels.embed import get_embed_wheel
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/__init__.py", line 3, in <module>
    from .run import cli_run, session_via_cli
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/run/__init__.py", line 11, in <module>
    from ..seed.wheels.periodic_update import manual_upgrade
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/seed/wheels/__init__.py", line 3, in <module>
    from .acquire import get_wheel, pip_wheel_env_run
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/seed/wheels/acquire.py", line 11, in <module>
    from .bundle import from_bundle
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/seed/wheels/bundle.py", line 4, in <module>
    from .periodic_update import periodic_update
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/seed/wheels/periodic_update.py", line 11, in <module>
    import ssl
  File "$HOME/.pyenv/versions/3.10.4/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/ssl.py", line 98, in <module>
    import _ssl             # if we can't import it, let the error propagate
ImportError: dlopen($HOME/.pyenv/versions/3.10.4/lib/python3.10/lib-dynload/_ssl.cpython-310-darwin.so, 0x0002): Library not loaded: /usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib
  Referenced from: [参照先情報] $HOME/.pyenv/versions/3.10.4/lib/python3.10/lib-dynload/_ssl.cpython-310-darwin.so
  Reason: tried: '/usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/usr/local/lib/libssl.1.1.dylib' (no such file), '/usr/lib/libssl.1.1.dylib' (no such file, not in dyld cache)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "$HOME/Library/Python/3.10/bin/poetry", line 10, in <module>
    sys.exit(main())
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/application.py", line 405, in main
    exit_code: int = Application().run()
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py", line 338, in run
    self.render_error(e, io)
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/application.py", line 180, in render_error
    self.set_solution_provider_repository(self._get_solution_provider_repository())
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/application.py", line 394, in _get_solution_provider_repository
    from poetry.mixology.solutions.providers.python_requirement_solution_provider import (  # noqa: E501
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/solutions/providers/__init__.py", line 3, in <module>
    from poetry.mixology.solutions.providers.python_requirement_solution_provider import (
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/solutions/providers/python_requirement_solution_provider.py", line 9, in <module>
    from poetry.puzzle.exceptions import SolverProblemError
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/puzzle/__init__.py", line 3, in <module>
    from poetry.puzzle.solver import Solver
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/puzzle/solver.py", line 16, in <module>
    from poetry.puzzle.provider import Indicator
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/puzzle/provider.py", line 27, in <module>
    from poetry.packages.direct_origin import DirectOrigin
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/packages/direct_origin.py", line 10, in <module>
    from poetry.inspection.info import PackageInfo
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/inspection/info.py", line 26, in <module>
    from poetry.utils.env import EnvCommandError
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/utils/env/__init__.py", line 10, in <module>
    from poetry.utils.env.env_manager import EnvManager
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/utils/env/env_manager.py", line 17, in <module>
    import virtualenv
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/__init__.py", line 3, in <module>
    from .run import cli_run, session_via_cli
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/run/__init__.py", line 11, in <module>
    from ..seed.wheels.periodic_update import manual_upgrade
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/seed/wheels/__init__.py", line 3, in <module>
    from .acquire import get_wheel, pip_wheel_env_run
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/seed/wheels/acquire.py", line 11, in <module>
    from .bundle import from_bundle
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/seed/wheels/bundle.py", line 4, in <module>
    from .periodic_update import periodic_update
  File "$HOME/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/virtualenv/seed/wheels/periodic_update.py", line 11, in <module>
    import ssl
  File "$HOME/.pyenv/versions/3.10.4/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/ssl.py", line 98, in <module>
    import _ssl             # if we can't import it, let the error propagate
ImportError: dlopen($HOME/.pyenv/versions/3.10.4/lib/python3.10/lib-dynload/_ssl.cpython-310-darwin.so, 0x0002): Library not loaded: /usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib
  Referenced from: [参照先情報] $HOME/.pyenv/versions/3.10.4/lib/python3.10/lib-dynload/_ssl.cpython-310-darwin.so
  Reason: tried: '/usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/usr/local/lib/libssl.1.1.dylib' (no such file), '/usr/lib/libssl.1.1.dylib' (no such file, not in dyld cache)

対応

まず、ログからpyenvでは3.12.0をインストールして、global指定しているにも関わらず、poetryでは3.10系で動作しているのが気になりました。 環境構築がpyenvと連動していないようにも感じたため、pyenvpoetryの仕様を確認し、poetryを再インストールすることにしました。

python 3.10とopensslの依存関係

調べると以下のissueが見つかりました。python 3.10ではOpenSSL >= 1.1.1を必要としているようですが、openssl@1.1と比較してバージョンは低いので、これがMacでは関連があるのかわかりませんでしたが、しかし、openssl@1.1に依存いる可能性はありそうだと推測しました。

Python 3.10 OpenSSL 設定の問題 ·問題 #91019 ·python/cpython:

github.com

pyenv環境の確認

念の為、pyenvのインストールに必要な情報を確認します。

Mac OS X:

If you haven't done so, install Xcode Command Line Tools (xcode-select --install) and Homebrew. Then:

brew install openssl readline sqlite3 xz zlib tcl-tk

上記は現状問題なくインストールされていることを確認しました。

pyenv-suggested-build-environment:

github.com

Poetryの再インストール

Poetryの公式手順を確認してアンインストール、インストールを実行します。

installing-with-the-official-installer:

python-poetry.org

<注意事項>一部環境変数に置き換えています。

% curl -sSL https://install.python-poetry.org | python3 -
Retrieving Poetry metadata

# Welcome to Poetry!

This will download and install the latest version of Poetry,
a dependency and package manager for Python.

It will add the `poetry` command to Poetry's bin directory, located at:

$HOME/.local/bin

You can uninstall at any time by executing this script with the --uninstall option,
and these changes will be reverted.

Installing Poetry (1.6.1): Done

Poetry (1.6.1) is installed now. Great!

To get started you need Poetry's bin directory ($HOME/.local/bin) in your `PATH`
environment variable.

Add `export PATH="$HOME/.local/bin:$PATH"` to your shell configuration file.

Alternatively, you can call Poetry explicitly with `$HOME/.local/bin/poetry`.

You can test that everything is set up by executing:

`poetry --version`

インストール後以下を実行します。

  • ~/.zprofileexport PATH="$HOME/.local/bin:$PATH"を追加
  • poetry config virtualenvs.in-project trueを実行して仮想環境下に.venvを作成するように変更

ここで、~/.zprofileを確認すると3.10を指定していました。 もしかすると下記を修正して、3.10より大きいバージョンをインストールすることでSSL(openssl@1.1)のエラーは解消する可能性もあります。

# poetry
#export PATH="$HOME/Library/Python/3.10/bin:$PATH" # 無効(コメントアウト)
export PATH="$HOME/.local/bin:$PATH" # 追加

インストール後の動作確認

poetry newコマンド:OK

% poetry new my_project
Created package my_project in my_project

poetry self updateコマンド:OK

% poetry self update
Updating Poetry version ...

Using version ^1.6.1 for poetry

Updating dependencies
Resolving dependencies... Downloading https://files.pythonhosted.org/packages/41/3a/2e2e902afcd751738e38d88af976fc4010b16e8e821945f4cbf32f75f9c3/msgpack-1.0.7-cResolving dependencies... Downloading https://files.pythonhosted.org/packages/38/bd/45ac5374fde553fc9912be2f5029a8a8dc9f2d52e39a6fb6b73acba39b2b/dulwich-0.21.6-Resolving dependencies... (2.9s)

No dependencies to install or update

まとめ

  • openssl@1.1のアンインストールに伴う、poetryコマンドが実行できない問題に関する現象と解決方法を紹介しました。
  • 前回の記事ではexpectコマンドが依存関係にあることを説明しましたが、brewコマンドで管理していないコマンド、その他アプリについても影響確認する必要があると思います。
  • 実行エラーになる場合は依存関係を確認し、対処する手間はありますが、latestであればopenssl@3に対応していると思うので最新のバージョンに更新することで問題が解消するか確認することが必要かと思います。

以上です。

brew doctorでopenssl@1.1が警告表示される(deprecated)現象と解決方法について

要約

  • brew doctoropenssl@1.1が非推奨と警告が表示されたので対応しました。
  • 参考記事を元にperlを更新しましたが、警告表示は変わらなかったため、依存関係を確認してexpectを再インストールすることで対応しました。

注意事項

  • 以下は利用環境に依存しますので参考記事も確認して慎重に実行してください。
  • 最新のperlを使用することについてはデメリットはないと思いますが、自己責任でお願いします。(openssl@1.1アンインストール時のエラー出力を確認してください。)
  • homebrewで管理していないコマンドも影響を受ける可能性があるので注意してください。(多くのコマンドはopenssl@3に対応してると思いますが。)

実行環境

% sw_vers
ProductName:        macOS
ProductVersion:     13.6.1
BuildVersion:       22G313

% brew --version
Homebrew 4.1.17

現象

openssl@1.1deprecatedと表示されていました。

% brew update
Already up-to-date.
% brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: Some installed formulae are deprecated or disabled.
You should find replacements for the following formulae:
  openssl@1.1

公式

formulae.brew.sh

対応

参考記事を元にperlのインストールとopenssl@1.1のアンインストールを実施

参考記事:

qiita.com

qiita.com

% perl --version

This is perl 5, version 30, subversion 3 (v5.30.3) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)

Copyright 1987-2020, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

% type perl
perl is /usr/bin/perl

% brew install perl
==> Downloading https://formulae.brew.sh/api/formula.jws.json

==> Downloading https://formulae.brew.sh/api/cask.jws.json
######################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/perl/manifests/5.38.0
######################################################################### 100.0%
==> Fetching dependencies for perl: berkeley-db
==> Downloading https://ghcr.io/v2/homebrew/core/berkeley-db/manifests/18.1.40_2
######################################################################### 100.0%
==> Fetching berkeley-db
==> Downloading https://ghcr.io/v2/homebrew/core/berkeley-db/blobs/sha256:a6b047
######################################################################### 100.0%
==> Fetching perl
==> Downloading https://ghcr.io/v2/homebrew/core/perl/blobs/sha256:db18bcd070562
######################################################################### 100.0%
==> Installing dependencies for perl: berkeley-db
==> Installing perl dependency: berkeley-db
==> Downloading https://ghcr.io/v2/homebrew/core/berkeley-db/manifests/18.1.40_2
Already downloaded: $HOME/Library/Caches/Homebrew/downloads/dad399d41acac3c682869c3c11caa898079e60cc1336af2d7ec80b5538bddfb6--berkeley-db-18.1.40_2.bottle_manifest.json
==> Pouring berkeley-db--18.1.40_2.ventura.bottle.tar.gz
🍺  /usr/local/Cellar/berkeley-db/18.1.40_2: 44 files, 5.9MB
==> Installing perl
==> Pouring perl--5.38.0.ventura.bottle.tar.gz
==> Caveats
By default non-brewed cpan modules are installed to the Cellar. If you wish
for your modules to persist across updates we recommend using `local::lib`.

You can set that up like this:
  PERL_MM_OPT="INSTALL_BASE=$HOME/perl5" cpan local::lib
And add the following to your shell profile e.g. ~/.profile or ~/.zshrc
  eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib=$HOME/perl5)"
==> Summary
🍺  /usr/local/Cellar/perl/5.38.0: 2,504 files, 67.8MB
==> Running `brew cleanup perl`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> Caveats
==> perl
By default non-brewed cpan modules are installed to the Cellar. If you wish
for your modules to persist across updates we recommend using `local::lib`.

You can set that up like this:
  PERL_MM_OPT="INSTALL_BASE=$HOME/perl5" cpan local::lib
And add the following to your shell profile e.g. ~/.profile or ~/.zshrc
  eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib=$HOME/perl5)"

perlのインストール後にバージョン確認

% perl --version

This is perl 5, version 38, subversion 0 (v5.38.0) built for darwin-thread-multi-2level

Copyright 1987-2023, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at https://www.perl.org/, the Perl Home Page.

% type perl
perl is /usr/local/bin/perl

openssl@1.1を強制的に削除する

% brew uninstall --ignore-dependencies openssl@1.1
Uninstalling /usr/local/Cellar/openssl@1.1/1.1.1w... (8,101 files, 18.5MB)

Warning: The following openssl@1.1 configuration files have not been removed!
If desired, remove them manually with `rm -rf`:
  /usr/local/etc/openssl@1.1
  /usr/local/etc/openssl@1.1/cert.pem
  /usr/local/etc/openssl@1.1/ct_log_list.cnf
  /usr/local/etc/openssl@1.1/ct_log_list.cnf.dist
  /usr/local/etc/openssl@1.1/misc
  /usr/local/etc/openssl@1.1/misc/CA.pl
  /usr/local/etc/openssl@1.1/misc/tsget
  /usr/local/etc/openssl@1.1/misc/tsget.default
  /usr/local/etc/openssl@1.1/misc/tsget.pl
  /usr/local/etc/openssl@1.1/misc/tsget.pl.default
  /usr/local/etc/openssl@1.1/openssl.cnf
  /usr/local/etc/openssl@1.1/openssl.cnf.dist

Warning: The following may be openssl@1.1 configuration files and have not been removed!
If desired, remove them manually with `rm -rf`:
  /usr/local/etc/openssl
  /usr/local/etc/openssl@3

openssl@1.1関連のファイルは記載の通り削除しました。

rm -rf /usr/local/etc/openssl@1.1

<補足>openssl@1.1の代替について

opensslを確認するとopenssl@3がインストールされていました。
ログは記録し忘れましたが、openssl@1.1openssl@3がインストールされていました。
openssl@1.1は削除していたのでopenssl@3のみ表示されています。

 % brew list -1 | grep openssl*
openssl@3

openssl@1.1以外に公開されているopensslは以下でした。

formulae.brew.sh

formulae.brew.sh

差異がわからなかったので、差異とインストールについてchatgptで確認しました。
以下の差異があるようです。(2023/10/26時点)

したがって、どちらをインストールするかは、あなたが使用するアプリケーションやシステムの要件によります。一部のアプリケーションは特定のバージョンのOpenSSLを必要とする場合があります。そのため、それらのアプリケーションがopenssl@3.0に依存している場合は、openssl@3.0をインストールすることをお勧めします。しかし、最新の機能やセキュリティ更新を利用するためには、openssl@3(現在のバージョン3.1.3)をインストールすることをお勧めします。

私の環境ではopenssl@3を使用し、openssl@3.0は使用しない(追加インストールはしない)ことにしました。

再度brew doctorを実行するもopenssl@1.1に依存ありの警告が表示される

ここまでで警告表示は解消されると思いましたが消えませんでした。

% brew doctor 
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: Some installed formulae are missing dependencies.
You should `brew install` the missing dependencies:
  brew install openssl@1.1

Run `brew missing` for more details.

brew missingコマンドを実行して依存関係を確認する

記載の通り依存関係を確認しました。 実行結果はexpectのみでした。

Run `brew missing` for more details.
% brew missing
expect: openssl@1.1

念の為、brew usesコマンドでopenssl@1.1に依存するパッケージを探す

実行結果はexpectのみでした。

% brew uses --installed openssl@1.1                    
expect

openssl@1.1がインスートされていることを確認する

expectはhomebrewでインストールされていました。

% brew list -1 | grep expect
expect

expectを更新する

念の為、更新有無を確認します。

% brew upgrade expect 
Warning: expect 5.45.4_2 already installed

expectを再インストールする

最新ですが念の為再インストールします。これは不要かもしれません。

% brew reinstall expect
==> Downloading https://ghcr.io/v2/homebrew/core/expect/manifests/5.45.4_2-2
######################################################################### 100.0%
==> Fetching expect
==> Downloading https://ghcr.io/v2/homebrew/core/expect/blobs/sha256:25d93f37370
######################################################################### 100.0%
==> Reinstalling expect 
==> Pouring expect--5.45.4_2.ventura.bottle.2.tar.gz
🍺  /usr/local/Cellar/expect/5.45.4_2: 70 files, 767.5KB
==> Running `brew cleanup expect`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).

brew cleanupでキャッシュを削除する

brew cleanup expectが出力されているため実行します。結果、警告表示は解消しました。

% brew cleanup expect
% brew doctor
Your system is ready to brew.

まとめ

brew doctoropenssl@1.1が警告表示される(deprecated)現象と解決方法について紹介しました。
homebrewで管理していないコマンドも影響を受ける可能性がありますが、openssl@1.1は非推奨なのでエラー内容を確認し対応することをおすすめします。(多くのコマンドはopenssl@3に対応してると思いますが。)