Python開発の初現場を終えて、学んだこと

f:id:monozukuri-bu:20191016153457j:plain

4月に新卒として入社し、先輩エンジニアと一緒にPythonでの開発を経験しました。
そこで学んだことを整理したいと思います。

開発環境

・言語
 Python 3.7

・ORM
 SQLAlchemy

・データベース
 PosgreSQL

コーディングにはVSCodeを使用しました。

プロジェクトで携わった部分

プロジェクトでは、比較的納期が長く、簡単な以下の機能開発を担当させていただきました。

・DBから特定のデータを取得、整形し、所定のフォーマットでエクスポートする機能
・エクスポートされたデータを、別環境のDBにインポートする機能

機能自体はシンプルですが、最大で同時に約5000万件ほどのデータを扱うため、Pandasなどで処理できない量ではありませんが、少なくもないという絶妙なデータ量でした。

苦労した点

設計には関わっていなかったため、設計書の内容をそのまま実装しただけでしたが、処理自体はそこまで複雑なものではありませんでした。
ただ、データ量が想像していたよりも多く、メモリ不足や速度の面で試行錯誤が必要になったことが苦労しました。

データのエクスポート機能

まずは自力で実装

設計書には実現したい機能と処理の流れが記載されていましたので、Pandasとfor文で実装しました。
この段階では、自分一人で要求されていた機能を実装することができました。
ただ、いざ動かしてみると、1日分のデータをエクスポートするのに約30分掛かっており、実際の利用シーンで想定されるのは1ヶ月〜3ヶ月分とのことだったので、この処理速度では話になりませんでした。

原因の特定と解決策

というわけで先輩エンジニアに相談し、コードの改良に入りました。
まずはじめに、pstatsというライブラリを使用してコードのボトルネックを特定する作業に入りました。
その結果、やはりfor文の使い方が適切でなく、無駄にループしていたりネストが深いのではないかということがわかりました。

この課題の解決策として、Pandasの関数を使用して可能な限り列や行に対してまとめて処理するようにと先輩エンジニアからアドバイスを頂きました。
この修正を行うことで処理時間を大きく減らすことに成功し、1か月分で約15分という許容範囲に収めることができました。

また、ロジックの共通化やコメントの追加なども、ご指摘を頂いていました。
修正作業と合わせて指摘を反映していくと、自分が書いたコード量の約半分の記述で、より高速に動作し、理解しやすいコードに変身しました。

データのインポート機能

まずは自力で実装

こちらはエクスポート機能と同じ要領でまとめて処理するように実装し、データを整形する部分ではそれほど時間は掛かりませんでした。
ただ、データをテーブルにINSERTする部分が2時間近く掛かる状態になってしまいました。
このINSERT処理は、SQLAlchemyというORMを介して行っていました。

課題の原因と解決策

先輩エンジニアに状況を伝えたところ、INSERTを実現する処理には様々な方法があるので、色々試してみるとよいとのことでした。

最初に考えたのは、Pandasのdf.to_sqlを使用してDataFrameを直接テーブルにINSERTする方法です。
これでも処理時間は大幅に短くなりましたが、それでもまだ1時間近く掛かっていました。
他にも色々と試行錯誤を重ねた結果、最終的にはORMは使用せず、Psycopg2を使用してPosgreSQLのcopy_fromでINSERT処理を行うことにしました。
その結果、2時間掛かっていた処理を30分程度まで短縮することができ、許容範囲内に収めることができました。

プロジェクトの経験を通して勉強になったこと

・ロジックの共通化
・コードが短くなるアルゴリズムの組み方
・第3者が読んで理解しやすいコードの書き方
 (PEP8などのコード規約や変数名の定義、コメントの記述)
・テストコードや仕様書の書き方

今まではプログラムが動けば問題ないと思っていました。
しかし、ロジックをできる限り関数で共通化し、コードをわかりやすくしておくと仕様変更があった際にも比較的容易に対処でき、かつ保守性も高まります。
分かりやすいコードを書くということが実際の業務において必要不可欠だということが、今回の案件で身をもって理解できました。

またアルゴリズムの組み方だけでなくテストや開発書類の書き方についてなども、スキルの高いエンジニアの方々にフォローしてもらったことが非常に勉強になりました。