依存モジュールが少ないソースコードを読む - スペシャリスト岡野真也に聞くPythonの読み方と使い方

現在、多くの支持を集めるPython。10年以上にわたりPythonを使い続ける岡野真也さんに、同言語の学び方、使い方を聞きました。

依存モジュールが少ないソースコードを読む - スペシャリスト岡野真也に聞くPythonの読み方と使い方

機械学習やデータサイエンスの隆盛に伴い、Pythonは多くの人に使われる言語になりました。GitHubの「The State of the Octoverse 2019」のレポートによると、GitHubリポジトリのコントリビューターから人気のあったプログラミング言語として、PythonはJavaScriptに次いで2位となっています。

「さまざまな課題を、楽に解決できるのがPythonの魅力」と語るのは、10年以上も前からPython・Djangoフレームワークのヘビーユーザーであり続けてきた岡野真也(おかの・しんや/ 1@tokibitoさん。彼はいかにして、設計や実装の技術を磨いてきたのでしょうか。そして、言語の特性を最大限に引き出すノウハウとは。より良いPythonの書き手になるために必要な知恵を伺いました。

2
株式会社ObotAI取締役 CTO、株式会社オープンコレクター 取締役。PythonとDjangoフレームワークのスペシャリストとして知られる。2006年、大学時代にPython製のCMSであるPloneに触れたことから、Pythonを使用し始める。2007年に札幌のSIerに就職。2008年に株式会社ビープラウドへと転職する。2016年より株式会社オープンコレクターに転職し、システムアーキテクトとして幅広い業務を担当。オープンコレクターのクライアントの一社であったObotAIから仕事ぶりを高く評価され、同社の取締役 CTOを兼任する。著書に『Pythonプロフェッショナルプログラミング 第2版』『Pythonプロフェッショナルプログラミング』『Google App Engineプログラミング入門』。自身のブログ『偏った言語信者の垂れ流し』でも、Pythonに関する情報をコンスタントに発信している。

Pythonは学習コストが低く、可読性も高い言語

——岡野さんは何をきっかけに、Pythonを使い始めたのですか?

岡野 Pythonを使い始めたのは2006年で、当時の私は大学生でした。大学の研究室でPython製のCMSであるPloneを用いており、Ploneの挙動をカスタマイズするにはPythonを書く必要がありました。見よう見まねでPythonを書くところからのスタートです。

より本格的にPythonを書くようになったのは、2007年からですね。その年に、Djangoフレームワークを触り始めました。個人のブログを立ち上げようと思ったのですが、Ploneは個人で使うには複雑で学習コストも高い。「他に、Python製の良いフレームワークはないだろうか」と探していたら、偶然「Djangoフレームワークで簡単なブログをつくってみた」という趣旨の記事を見かけて、これがDjangoとの出会いになりました。

——Pythonの利点としては、どのような点が挙げられますか?

岡野 Pythonは文法がシンプルで、予約語の種類が少ないです。学習コストが低く、他の人の書いたコードも読みやすい。コーディングでは書いている時間よりも読んでいる時間の方が圧倒的に多くなるものです。「読みやすい」とは言語として重要な特性だと思うのです。それからPythonには多種多様なモジュールが用意されているため、何か実現したいことがある場合に、それらのモジュールを活用できるケースが多いです。

——なるほど。Djangoフレームワークに関してはいかがでしょうか。

岡野 Djangoフレームワークの初期に感じた利点は、生成されるファイルの種類が圧倒的に少ないことです。

他のWebフレームワークの場合、プロジェクトを自動生成した際に大量のファイルが作成されるものもあります。一方でDjangoフレームワークは、私が使い始めた頃のバージョンではプロジェクト新規作成時に3~4個くらいのファイルしか生成されませんでした。

当時の私はプログラミングスキルがそれほど高くありませんでしたが、ファイル数が最低限であることで「どこに何を記述すればいいのか」が明確になり、簡単に実装を進められました。

さらに、Djangoフレームワークには組み込みの管理画面がついていますが、この機能は非常によくできています。Modelクラスと少しの設定を書けば、それだけで各テーブルのデータを参照・編集できる管理画面が使えるようになります。そのままプロダクションでも使えるくらいのクオリティーですし、カスタマイズも容易です。

3

Djangoフレームワークの管理画面。

——その機能を用いることで、開発やテスト、運用が非常に楽になりそうですね。

岡野 他には、Djangoフレームワーク内蔵のアプリケーションと呼ばれる仕組みが便利です。これは、Pythonモジュールの形でアプリケーションをインストールして、設定ファイルによって特定のアプリケーションを有効にすることで、さまざまな機能を導入できるというものです。

INSTALLED_APPS = [
    # ...
    'some_app_name.apps.SomeAppConfig',
    'debug_toolbar'
]

Djangoフレームワークでは、特定のPythonモジュールをインストールした後、settings.pyのINSTALLED_APPSという項目に上記フォーマットで設定を記述することで、該当のアプリケーションが有効化される。

——読者の方におすすめの、開発に役立つアプリケーションはありますか?

岡野 Django Debug Toolbarが便利です。これは、開発中にWeb画面の右側にデバッグ用の情報(リクエスト・レスポンスの詳細や実行されたSQL、セッションの内容など)を表示できる機能です。

多種多様なアプリケーションを利用して開発の利便性を向上させられるという意味でも、Djangoフレームワークは非常に優れています。

Pythonの設計を学ぶには、ライブラリのコードを読むべし

——Pythonの言語特性を学ぶためには、何を学習をするといいでしょうか?

岡野 おすすめは、さまざまなライブラリのソースコードを読むことです。先ほど、Pythonのコードは読みやすいという話をしましたが、コード量が少ないものであれば、サードパーティのライブラリも読むのはそれほど難しくはありません。私もPythonを学びたての頃は、よくDjangoフレームワークのソースコードに目を通していました。

——Djangoフレームワーク以外には、どのようなライブラリやフレームワークのソースコードが読みやすいですか?

岡野 HTTP通信ライブラリであるRequestsモジュールや、Webアプリケーションのリクエストとレスポンスをオブジェクト化するためのWebOb、また、Pythonに内包されている各種標準モジュールもおすすめです。選定基準としては「依存しているモジュールの種類が少ないこと」を軸にするといいと思います。サードパーティ製のモジュールに依存しておらず、Pythonの標準モジュールだけに依存しているようなものが参考になると思います。

——コードリーディングにおいて、初心者はどのような点に着目して読むと、より効果的でしょうか?

岡野 クラスやモジュール、関数などが「どのような単位で分けられているか?」を見ていくといいです。広く使われるライブラリのソースコードを読み解いていけば「この単位でモジュール分割することで、メンテナンスがしやすくなる」という感覚がつかめます。

4

——岡野さん自身は、Djangoフレームワークのソースコードを読んで、どのようなことを学ばれましたか?

岡野 例えば、オブジェクト指向プログラミングでは基本的なことなのですが、「クラス内の'__init__' メソッド(初期化の処理)に初期化以外の意味のある処理を含めない」などでしょうか。初期化の処理はクラスを使用するとき必ず呼ばれますから、クラスのオブジェクトを準備する以外の処理を書いてしまうと、影響範囲が非常に大きくなってしまい、テストもしづらくなります。何か処理を実行したいならば、別のメソッドを用意し、そのなかで行うべきだと学びました。

他には、先ほどの話にも出てきましたが、Djangoフレームワークのアプリケーションにおけるpluggableの設計からも多くの学びを得ました。Djangoフレームワークでは各機能ごとに抽象化されたクラスが用意されていて、これらを継承したクラスを利用することで、各機能のふるまいを変えることができます。Django以外のWebアプリケーションフレームワークでもよくある設計ですが、これは自分でライブラリやモジュールを作成する際に、かなり参考になりました。

また、Djangoフレームワークでは、設定ファイルがPythonのモジュールになっていて、例えば有効にするアプリケーションの情報は文字列のリストで設定します。すると、その名前を持ったモジュールがあるかどうかを探索して読み込んでくれる。つまり、設定ファイル内では直接的にモジュールのインポートを行っていません。

この設計を用いると、設定ファイルであるPythonモジュールがアプリケーションコードへ依存し、循環参照になってしまう問題を回避できます。これにより、循環参照が発生しにくいプラグインのような仕組みを実現できているのも、興味深いと感じました。

パフォーマンス課題を解決するために採用すべきアプローチ

——Pythonは「処理速度が遅い」という意見が持たれることもあります。

岡野 確かに、Pythonはソースコードをコンパイルしてバイトコードに変換してからVMが実行するという処理の流れになっているため、ある程度遅くなるのは言語仕様上の必然ではあります。

——その課題を解決するには、どのようなアプローチをとるべきでしょうか?

よく用いられる手法はモジュールをC言語やCythonなどで作成し、Python側から呼び出すことでパフォーマンスを向上させるという解決策です。実際、パフォーマンスを気にするサードパーティ製のPythonモジュールはC言語で書かれていることがよくあります。

——他には、どのようにしてパフォーマンスの最適化を図ることが可能ですか?

岡野 前提として、Webアプリケーションやバッチ処理などでパフォーマンスに問題が生じるのは、実際はプログラミング言語の処理速度ではなくI/O周りやSQLに課題があるケースが多い。

I/O待ちが原因でパフォーマンス劣化を引き起こしているならば、並列処理や非同期I/Oなどを用いて解決できるケースも多いです。原因を特定するには、アプリやサーバーの挙動を計測し、どの箇所がボトルネックになっているかを探ることが重要になります。

もしも調査をしたうえで、他の原因ではなく本当にPythonの処理速度が問題であると判明したならば、別の言語への切り替えや、PyPyなどパフォーマンスに優れた別のPython実装を使うアプローチも考えられます。

ただしPyPyは、私たちがよく使用している公式版のPython(CPython)とは当然ながら内部実装が異なっているので、機能の互換性に問題が生じることもあります。例えば、PyPyではガベージコレクションに関する参照カウントの挙動が異なるため、サードパーティのライブラリがPyPyと相性が悪いケースも見られます。

とはいえ本当は、全く別のアプローチもあって。パフォーマンス最適化のために一番最初にすべきは「要件を落とすこと」だと私は考えます。実装で解決する、というアプローチが必ずしも根本課題の解決ではないこともあります。もっと上流の段階で課題を解決した方が、設計や実装が楽になるケースも多いはずです。

影響の大きかった、2系から3系への非互換変更

エンジニアHubに会員登録すると
続きをお読みいただけます(無料)。
登録のメリット
  • すべての過去記事を読める
  • 過去のウェビナー動画を
    視聴できる
  • 企業やエージェントから
    スカウトが届く