• python
  • programming
  • learning
  • sdk

週末で Python を学ぶ:ゼロからプロジェクト完了まで

新しいプログラミング言語をどのように迅速に学べるでしょうか?この記事では、Python を使って完全なプロジェクトを構築する週末の経験を共有します。

Gao
Gao
Founder

はじめに

アイデンティティサービスとしての Logto において、さまざまなプログラミング言語やフレームワークでスムーズな体験を提供することは重要です。これはしばしば、ソフトウェア開発キット (SDK) の作成を含みます。しかし、プログラミング言語が私たちの技術スタックの外にあり、チームに慣れ親しんだ経験がない場合、強力な SDK を作成することは挑戦となります。

Python は私たちにとってそのような課題でした。たくさんの Python ユーザーがいるにもかかわらず、Python SDK がないことは長年気がかりでした。この問題に対処するために、私はそのギャップを埋めることを決意しました。

私には何年ものプログラミング経験がありますが、Python はまだそれほど踏み入れていません。数年前に Python 2 を簡単なスクリプトのために少し触れたことはありますが、私の知識は時代遅れでした。それでも、今こそ飛び込む時です!

1日目: 基盤を固める

目標を定義する

私の経験から、新しいプログラミング言語を学ぶ最も効果的なアプローチは、完全なプロジェクトを作成することです。幸いなことに私たちの目標は明確でした:Logto の Web アプリ向け Python SDK を構築することです。

コードに飛び込む前に、それを分解して考えてみましょう。以下がそのリストです:

  1. サインイン、サインアウト、ユーザー情報、トークン管理などのタスクを行うための Logto クライアントを作成します。
  2. SDK の使用方法を示すチュートリアルとサンプルプロジェクトを提供します。
  3. ユーザーが簡単にインストールできるように SDK をどこかに公開します。

タスク 1 が最も多くの作業を含んでいるようなので、その範囲を確認し、さらに細分化する必要があります。プロジェクトの境界を確保し、スコープの膨張や過度のエンジニアリングを避けるために、このステップは重要です。

チームによる以前の作業が、私の時間を大いに節約してくれました:

  • SDK の構造と API デザインを概説した SDK の規約
  • 異なる言語の既存の SDK は、Python に対するパターンと潜在的な改善点についての洞察を提供してくれました。

これらのリソースを参照することで、何をすべきかがはっきりと見えてきました。詳細はこの記事の範囲を超えますが、次に進みましょう。

環境の設定

私は Mac を使用しているので、Python はすでにインストールされています。しかし、Python のバージョンを管理するためのより良い方法があるかどうか考えていました(バージョン互換性の痛みを聞いたことがあります)、Node.js の nvm のようなものです。すぐに pyenv を見つけ、直接インストールを開始しました。

次の議題は、パッケージマネージャーと依存関係の管理です。通常、これらは互いに結びついています。では、なぜ pip(Python のデフォルト)ではないのでしょうか?requirements.txt を見ると、それが単なるバージョン付きパッケージのリストであることがわかります。これは他のプロジェクトで使用されるかもしれない SDK にとっては十分ではありません。たとえば、開発のためにいくつかのパッケージを追加する必要があるかもしれませんが、それらを最終的な SDK に含めたくないのです。requirements.txt はこれらを処理するにはシンプルすぎるのです。

他のプログラミング言語が技術スタックにある場合の利点の1つは、「Python の同等品」を検索できることです。そこで「package.json Python 同等品」を検索し、Poetry を見つけました。これは次のとおりです:

  • それはパッケージマネージャー、依存管理、仮想環境管理を兼ねたものです。
  • それには、Node.js の package.json に似た pyproject.toml ファイルがあります。
  • 確定された依存関係のバージョンを記録するロックファイルを使用します。

現代の CLI は、新しいプロジェクトに合わせた init コマンドを含むことが多いです。Poetry もその例外ではありません。コマンドを実行すると、pyproject.toml ファイルが作成されました。

最初のコード行

ついに、コードを書く時がやってきました。クラシックな「Hello, World!」プログラムから始めるのは、常に良い選択です。プログラミング言語を学ぶ際、フル機能の IDE は必須ではありません。コミュニティに支援されたエディタ、例えば VS Code で十分です。

私たちの SDK が Web アプリに焦点を当てているので、人気のあるフレームワーク Flask を利用してシンプルな Web サーバーから始めました。

Poetry の機能を活用し、Flask をインストールするには、単に poetry add flask と実行するだけで済みます。その後、Flask の公式クイックスタートガイドに従って、次のように 'hello.py' ファイルを作成しました:

サーバーを flask --app hello run で起動し、ブラウザで http://localhost:5000 にアクセスすると、期待どおりの結果が得られました。それは動作しました!

初心者として、急いで多くのコードを書くことはしませんでした。むしろ、コードスニペットから得られる情報をたくさん学びました:

  • from x import y を使用してモジュールまたはクラスをインポートします。
  • 行の終わりにセミコロンは必要ありません(ああ、なんてことだ)。
  • 任意の名前を入力し、それに値を割り当てて変数を定義できます。
  • new キーワードなしでクラスのインスタンスを作成できます。
  • Python はデコレータをサポートしており、@app.route は関数をルートハンドラとして登録するデコレータとして機能します。
    • 関数の戻り値は応答本文として解釈されます。
  • 関数を定義するには、def キーワードを使用します。

ご覧のように、コードをただ「動作させる」のではなく、各行のコードを理解しようとすることで、多くを学ぶことができます。同時に、Flask の公式ドキュメントは、スニペットの詳細をさらに説明してくれます。

プロジェクト開始

今こそプロジェクトを開始する時です。すぐに LogtoClient クラスを定義し、言語を感じるためにいくつかのプロパティとメソッドを追加してみました:

その後、クラスと Flask を統合します:

それは本当のプロジェクトのように感じ始めました。でも、何かが欠けていると感じました:タイプシステムです。

タイプシステム

これは SDK であるため、タイプシステムを組み込むことで、ユーザーが API を理解し、開発時のエラーの可能性を減らすのに役立ちます。

Python はバージョン 3.5 で タイプヒント を導入しました。それは TypeScript ほど強力ではありませんが、何もないよりはましです。私は LogtoClient クラスにいくつかのタイプヒントを追加しました:

今でははるかに良くなりました。ただ、より複雑なタイプ、たとえば事前定義されたキーを持つオブジェクトなどを処理する場合、困難が生じます。たとえば、構成オブジェクトを表す LogtoConfig クラスを定義する必要があります:

それは見た目には大丈夫ですが、すぐに JSON からオブジェクトをエンコード、デコード、検証する問題に直面することになります。

いくつかの調査の結果、私は pydantic を解決策として選びました。これは、タイプヒントと連携するデータ検証ライブラリです。煩わしいボイラープレートコードに従わずに、多様な JSON 機能をサポートしています。

したがって、LogtoConfig クラスは次のように書き直すことができます:

また、クラス名の後にカッコを追加することで、Python でのクラス継承についても学びました。

非同期操作

Logto SDK 内で、Logto サーバーに HTTP リクエストを送信する必要があります。JavaScript の経験がある場合、「コールバック地獄」というフレーズに心当たりがあるでしょう。これは、非同期操作に対処する際の一般的な問題です。モダンなプログラミング言語は、「Promise」や「コルーチン」などの類似の解決策を提供します。

幸いなことに、Python には asyncawait のビルトインソリューションがあります。それらを使用する前に、人気のあるフレームワークとの互換性を確認してください。Flask では、async エクストラをインストールし、def の代わりに async def を使うことでこれを行うことができます:

その後、await を使って非同期操作の結果を待つことができます。

HTTP リクエスト

HTTP リクエストは興味深いトピックです。ほぼすべてのプログラミング言語にはネイティブのソリューションがありますが、使いやすさのためにサードパーティのライブラリがよく使われます。いくつかの例を挙げると:

  • JavaScript: XMLHttpRequest vs. fetch vs. axios
  • Swift: URLSession vs. Alamofire
  • Java: HttpURLConnection vs. OkHttp

これは Python でも当てはまります。私の決定は、asyncawait をサポートし、その人気も高い aiohttp を使うことでした。

Copilot の魔法

Copilot が登場する前、今はビジネスロジックを書く退屈な部分に差し掛かりました。SDK の規約や他の SDK の助けを借りて、各メソッドのコードを書く前に、詳細なコメントを書きました。

これによりコードの可読性が向上し、開発者はコードインテリジェンスを通じて API を理解するのに役立ちます。

たとえば、generateCodeChallenge メソッドについては、次のようにコメントを書くことができます:

これは、メソッド定義を明確なコメントで構成することで、LLM (大規模言語モデル) への優れたプロンプトとなりました。そして、Copilot は期待を裏切りませんでした:

いくつかの修正が必要な場合もありますが、それは問題ではありません。すでにゲームが変わっています。

まとめ

これは1日目の進捗です。長い一日でしたが、現代のツールとテクノロジーのおかげで、期待以上の進歩がありました。

2日目: ハードルを上げる

1日目の作業に基づいて、ビジネスロジックは迅速に完了しました。しかし、SDK にとってはまだ不十分です。2日目のタスクは以下です:

  • ユニットテストを追加します。
  • コードフォーマットを強制します。
  • Python バージョンの互換性を検証します。
  • 継続的インテグレーションを追加します。
  • SDK を公開します。

ユニットテスト

ユニットテストは多くの場合、私たちを救ってくれるので、スキップすることはありません。ユニットテストを書く際の一般的な考慮事項は次のとおりです:

  • テストをどのように整理して実行しますか?
  • 結果をどのようにアサートしますか?
  • 非同期テストをどのように実行しますか?(一見簡単に思えるかもしれませんが、いくつかの言語では問題を引き起こすことがあります。)
  • 依存関係をどのようにモックしますか?(それが不可欠でない限り、このトピックには深入りしないようにしてください。それはウサギの穴に入ることになります。)
  • コードカバレッジレポートをどのように生成しますか?

これらの質問を頭に入れた状態で、ビルトインの unittest モジュールは一部のケースでは不十分であると感じました。そこで、テストフレームワークとして pytest を選びました。非同期テストをサポートしており、十分に成熟しているようです。

この旅の中で、fixture などの興味深い新しい概念も発見しました。これにより、他の言語でコードを書く際にも役立つ思考が得られるでしょう。

コードフォーマット

すべての言語には独自のコードフォーマットスタイルがあります。個人的には、一貫したフォーマットは自身をハッピーで快適にしてくれますし、コードレビューやコラボレーションでも役立ちます。

「最適な」スタイルについて議論するのではなく、意見のあるフォーマッタを選び、それに従うことに決めました。

Black は良い選択肢のようです。唯一の不満は、タブサイズが変更できないことですが、それほど大きな問題ではありません。順応することにしました。

Python バージョンの互換性

SDK として、それは広く使用されている Python バージョンにわたって互換性があるべきです。「python version usage statistics」を検索して、Python 3.8 を最小バージョンとして使用することにしました。

ここで環境マネージャーの美徳が発揮されます。pyenv local 3.8poetry env use 3.8 を実行することで簡単に Python バージョンを切り替え、テストを実行して互換性の問題を明らかにできます。

継続的インテグレーション

継続的インテグレーションは、すべてのコード変更の品質を保証します。私たちのリポジトリが GitHub にホストされているので、GitHub Actions が自然な選択肢でした。

コアワークフローは以下の原則に従います:

  • 環境を設定します。
  • 依存関係をインストールします。
  • プロジェクトをビルドします(ただし、Python にはビルドは必要ありません)。
  • テストを実行します。

GitHub Actions には良いコミュニティがあるので、このワークフロー を構築するのに数分しかかかりませんでした。

マトリックス戦略を採用することで、異なる Python バージョンやさらには異なるオペレーティングシステムでワークフローを実行することができます。

SDK の公開

最後のステップは SDK を公開することです。公開パッケージの場合、公式の言語固有のパッケージレジストリに提出することで通常行われます。例えば、Node.js の場合 npm、Python の場合 PyPI、Swift の場合 CocoaPods です。

Poetry は私の道案内です。poetry publish を実行するだけで、PyPI にパッケージを公開できます。それはとてもシンプルです。

終わりに

それは魅力的な旅でした。オープンソースコミュニティの助けがなければ、はるかに困難だったでしょう。すべての貢献者に拍手を送りたいです!

以下はいくつかの一般的な考察です:

  • 目標を正確に定義し、それを分解し、常に目標を念頭に置いてください。
  • 安定し再現可能な開発環境を整えましょう。
  • (良い)ツールをできるだけ活用しましょう。
  • ビルトインまたは既存のソリューションを優先しましょう。
  • 言語の規約と書いたすべての行のコードを理解しましょう。
    • ただし、細部にこだわらないでください。
  • 明確で記述的なタスクには Copilot を使用しましょう。

最終的な成果物は このリポジトリ で見つけることができます。同様の戦略で、私はまた迅速に Logto PHP SDK も構築しました。何か提案があれば、ぜひお知らせください。

この記事が新しいプログラミング言語の学習に役立つことを願っています。ハッキングを楽しんでください!