🍴

食わず嫌いしていた Python を採用したらそこまで悪くなかった話

2024/04/02に公開

巷で Python が話題になっています。どんな話題かはさておき、「そういや自分、Pythonあんまり使いたくないと思ってたけど、結局新規プロダクトに採用してるし、半年経ったな」と振り返る良いきっかけになるかなと思ったので、食わず嫌いマンだった私が半年 Python でゼロイチのプロダクト開発をした感想を残します。

開発しているプロダクト

まだ公に出しているものではないので詳細は伏せますが、AI、機械学習系の新規プロダクトです。
チームはかなり少数精鋭ですが、技術選定における裁量をほぼ全面的にもらえており、稟議申請からインフラの構築、そしてPythonを用いたプロダクトの開発を初めて半年経ち始めた頃です。

必要最低限の機能に絞ったまだまだ小さいプロダクトですが、現在はいくつかの企業にお試しで使ってもらっていて、本格的に展開させたいなと考えているフェーズです。

現在の技術スタック

インフラ

基本 AWS ですが、要件によっては GCP, Azure をつまみ食いしている状態です。

バックエンド

言語:Python
フレームワーク:FastAPI + Strawberry-GraphQL

今回の主題となる部分です。 Strawberry-GraphQL に気になる方もいるかと思いますが、残念ながら今回は割愛します

フロントエンド

言語:TypeScript
フレームワーク: Next.js

初期は Vite + React だったのですが、Next.js に乗り換えました。ただし PagesRouterです。
乗り換えた理由としては、あるページだけを切り離してビルドするのが Vite だとかなり大変だったことと、DirectoryRooting, Layouts を手軽に使いたいという点でした。 最近は Next.js だとオーバースペック(?)だよねという意見もありますが、ドキュメントやナレッジの充実ぶりや、社内で他のチームが Next.js を採用しているというのが大きいです。

食わず嫌いしていた理由

チームが発足するかなり前から技術選定を任せてもらっていたのですが、AI, LLM が絡む特性上、Python が選択肢に上ります。
ただし、Python を使う時にいくつか懸念もあって、Python ユーザーには申し訳ないと思いつつ、食わず嫌いしてしまっていました。

  • 世間一般で良い噂を聞かないことに対する不安
  • 動的型付け言語なことに対する不安
  • ライブラリの管理方法が requirements.txt なことに対する不安
  • Python は遅いと言われていることに対する不安

世間一般で良い噂を聞かないことに対する不安

Twitterを見てても、Python が嫌い、ゴミだ、使いたくないという意見もよく聞きます。
技術選定をする際に周りに相談した時に、「1年ほど開発してたことはあるけど、おすすめはしない」という人がいたのも事実でした。
なんとなくですが、周りが嫌がっているものを導入するのってどうなんだろう?という気持ちもありました。

ただ、身近にいる人に相談したときに深掘りして聞いてみると「インターフェースがないから」「プライベートメソッドがないから」といった具体的な理由から、「メンテナンスしづらくなる」という言語特有の問題とは違うような意見もあったので、「そうなんだ」程度に留めたほうが良いなとその時は思っていました。

動的型付け言語なことに対する不安

上記で出た意見も関連しますが、私自身も今の時代に動的型付けを使う理由ってなんだろう?って真剣に考える良い機会でした。
なんとなくですが、Pythonは型に対する安全がなく、バグを埋め込みやすいそんなイメージで不安を持ってしまっていました。

ライブラリの管理方法が requirements.txt なことに対する不安

技術選定当初の私の理解では、依存ライブラリは requirements.txt を用いて pip でインストールするというのが当たり前で、バージョンのロックがなかったり、QiitaやZenn、GithubのReadmeを読んだ時に pip install を使ってインストールする、いわゆるグローバル環境に手をつけるインストールが普通な文化という印象を持っていました。

なんとなくですが、Pythonは依存ライブラリのバージョン問題の解決が大変そうなイメージで不安を持ってしまっていました。

Python は遅いと言われていることに対する不安

これはただ聞いただけで、実際に計測したわけでもなんでもないので、ただただそう思ってしまっていただけです。
今振り返るとよくないですね。

採用した理由

簡単なサンプルプロダクトを作ってみたり、いろいろな人の意見を聞いたり、メンバーの技術スタックを整理した上でバックエンドをPythonにすることに決めました。

  • AI 関連のプロダクトなので安定択?
  • チームの技術スタック

AI 関連のプロダクトなので安定択?

LLMを扱ったりするとなると、どうしても Python が主体になりやすいです。たとえばローカルLLMを呼び出す際は別サーバー、プロセスでPython用のコードを叩かなくても良いというメリットがあります。
個人的には仮に別の言語でバックエンドを実装したとしても、ローカルLLMを呼び出したい時は結局Pythonを使うことになると想定しましたし、そもそもいきなり別サーバーを用意するのは初期コストとしては大きいので最初は一つにまとめたいなという考えがありました。

チームの技術スタック

ほとんどこれが理由と言って過言ではないのですが、「メンバー全員が高速でプロダクトを作って売り上げを出す」を目標にしたときに Python が一番手っ取り早い、というものでした。

「食わず嫌い」と自称しているだけあって私は実務経験がなかったですが、一方で うちのメンバーには機械学習に精通したメンバーもおり、そういった知見、スキルを余すところなく使うにはPythonで進めたほうが成果が出ます。「であれば私がPythonを使えるようになればいい」という結論でした。
実際、Pythonの学習コストはかなり低いので、他言語の経験があれば1週間前後でプロダクト開発ができています。

また、同じ理由で、もしチームを拡大するとなった場合、候補に上がるのはAI、機械学習、LLMといったワードに対して精通した方を採用するだろうと思い、彼らが低い学習コストでプロダクトを作るためにも Python に寄せたほうが良いだろうと考えました

使ってみた感想

「食わず嫌い」をするほどでもなかった、反省。でも一番好きな言語になるかというと、そうではありません。すごくニュートラルな気持ちです。
今のところ大きく困ったことはありません。もしかしたら3年後、5年後とプロダクトが大きくなるにつれて問題が出てくるのかもしれません。
ただ、私が見聞きした範囲では「Pythonのせいでプロダクトのスケールができない」というよりは、「設計のコードの汚さ」が問題であって、スケールできないことの理由に「Pythonだから」というのはないと思います。
よくネットで書かれている「Pythonを採用しているサービス」で巨大なサービスがいくつも出てきますが、あれがもし"今も"そうなのだとしたら、規模のデカさと言語の相性に相関はないだろうと考えました。

世間一般で良い噂を聞かないことに対する不安

選定当初の頃、気にしすぎていたなと反省しています。ネットで書かれてることってマイナスな印象が増大されやすいので、目に入りやすいです。最近Twitterでも言われてますが、本当にダメなものって言及すらされないので、ある程度の知名度、利用頻度が増えるとこういうコメントはどうしても避けられないのかなと感じます。

使った人の意見も参考にすべきところはいくつかあると思っていて、以下は具体的に「動的型付け言語に対する不安」に紐づくのでそこで振り返ります

ただ、身近にいる人に相談したときに深掘りして聞いてみると「インターフェースがないから」「プライベートメソッドがないから」といった具体的な理由から、「メンテナンスしづらくなる」という言語特有の問題とは違うような意見もあったので、「そうなんだ」程度に留めたほうが良いなとその時は思っていました。

動的型付け言語なことに対する不安

動的型付けであることに限らずですが、インターフェースがない、プライベートメソッドがない、こういった意見も聞きます。
プライベートメソッドに関しては、小さな悩みとして今残っていますが、「インターフェースがない」に対しては ABC クラスを用いた抽象クラスという手が使えますし、なんなら Ruby と同じくダックタイピングという手法もあります。 go 言語もインターフェースはないですが、ある種のダックタイピングですしね。

Python の動的型付けについては、最近の型ヒントは結構うまく機能してくれていて、懸念していたほどではありませんでした。IDEを Pycharm を使っていてLanguageServerが賢い(?)というのもあるからもしれませんが、入力補完やエラー、警告である程度防げます。
そもそも、前のチームでは Ruby / Ruby on Rails を使っていたので、他の方ほど動的型付け言語に対する敷居が下がっていたのもあるかと思います。

Python は緩くやろうと思えば緩くできるし、型ヒントと mypy で厳格にやっていく塩梅が開発者に委ねられているので、できる限り「堅牢」なコードベースにしていくのが肝だと感じました。

このあたりは「ロバストPython」という書籍がとても良く参考になり、多くの不安と懸念を払拭してくれたのでおすすめです

動的型付け言語を選ぶことに対するリスクを考えた時にまずこの2つが浮かびました。

  • バグを生みやすいのではないか
  • コードの意図が読み手に伝わらないのではないか

私のチームでは、メソッドの引数、戻り値に型はつける、テストを書く、を丁寧にすることで致命的なバグの混入を防ぎ、コードの意図を明確にするよう心がけています。逆に言えば、静的型付けの良さはテストケースが減る、意図を明確にした書き方を強制できる点だと思います。

ちょっとしたR&D要素の高いことを「緩い」コードで書き、実用的だと判断したら「堅牢」なコードに書き直す、ここがPythonの強みを活かせるポイントかと思いました。

ライブラリの管理方法が requirements.txt なことに対する不安

poetry が全てを解決してくれました。最近だと Rye も主流になってきているので、好みで使うのが良いと思います。ちなみに弊CPOは pipenv 推しでした。

Python は遅いと言われていることに対する不安

これも確かにそうなんだろうとは思うんですが、私自身そんなにハイパフォーマンスなプロダクト作りに自信があるわけではないので、言語が限界を迎えるよりも前に、自分たちが作るプロダクトの設計、コードの書き方を丁寧にやるべきだよなと感じます。

特に LLM を扱うプロダクトは最大のボトルネックが生成に関わる部分なので、いくら言語が高速に動作したとしてもユーザーの体感する速度とは別だと思っています。
今の私が議論にあげられるとしたら、設計やコードの書き方、外部IO、データベースのチューニングをした上で初めてまともにできるかなという感じでした。

まだ視野が狭い感は否めないので、言語の速度が問題になって困っている開発者さんの話も聞いてみたいので、そこらへんお気軽にコメントいただけると助かります。

まとめ

AI関連のプロダクトであるなら、Pythonを扱えるメンバーが自然と集まると思うのでその中で選択肢に入れるのは非常に良いと思います。特に、「すぐにでも売上を出さなければ」という状況で開発する場合はPythonやRubyのような動的型付け言語でサクっと作る、というのは非常に重要です。
ただし、「サクッと作る」のと「雑に作る」のは別の話で、堅牢で安全に早く作る良いバランスを与えてくれるのがPythonなのかなと感じました。

余談ですが、Pythonの以下 3つだけはどうしても好きになれません。慣れはしましたが。

  • リスト内包表記
  • lambda
  • aaaa if x = y else bbbb

弊CPOは「リスト内包表記なんてくそ簡単だよ!考え方はこうで、こうして〜〜」と楽しそうに語ってくれましたが、まだ技術選定当初の私の頭には入ってきませんでした。

改めて、巷で Python が話題になっていますが、私は使った方の批判や意見は理解しますし、尊重しています。
一方で、全く手をつけずに悪い印象だけで批判に乗っかったり、ネガキャンに乗せられて選択肢から外すのは非常に勿体無いなと思いますし、時間が許すなら色々触れて自分の言葉で語れるようにするのが大事かなと感じました。

GitHubで編集を提案

Discussion