tag:crieit.net,2005:https://crieit.net/users/515hikaru/feed 515hikaruの投稿 - Crieit Crieitでユーザー515hikaruによる最近の投稿 2020-02-25T01:17:50+09:00 https://crieit.net/users/515hikaru/feed tag:crieit.net,2005:PublicArticle/15733 2020-02-25T01:17:50+09:00 2020-02-25T01:17:50+09:00 https://crieit.net/posts/auto-generate-requirements-with-dephell requirements.txtの自動生成 〜Pythonスクリプトから依存パッケージを抽出する〜 <h1 id="この記事の概要"><a href="#%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%81%AE%E6%A6%82%E8%A6%81">この記事の概要</a></h1> <ul> <li><code>dephell</code> コマンドを使うと Python パッケージの依存関係記述ファイルの相互変換ができる <ul> <li>setup.py から requirements.txt を作るとか</li> </ul></li> <li>プロジェクトの Python パッケージの <code>import</code> を読み取って適切なフォーマットに変換できる</li> <li>依存関係が掲載されていないプロジェクトでも使えるのでオススメ</li> </ul> <h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1> <p>データの前処理や可視化はどうやったの?みたいな話で Jupyter Notebook が残っているけど、特に requirements.txt とか setup.py が残ってない、みたいなケースがままあると思います。</p> <p>もはや依存関係のバージョンの同定は不可能ですし、ほとんどの場合システムに組み込むとかしないので「動けばいい(再現すればいい)」のですが、そもそも動かすために依存するライブラリの一覧を作るのが一苦労です。ノートブックを開いて<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>、import 文からサードパーティのライブラリを特定して、requirements.txt を作る単純作業になります。</p> <p>そんなつまらない作業、自動化したいよな〜思うことでしょう。そんなときに使えるのが<a target="_blank" rel="nofollow noopener" href="https://github.com/dephell/dephell">DepHell</a>です。下記 1 コマンドだけで、スクリプトの import 文から requirements.txt を作ってくれます。</p> <pre><code>$ dephell deps convert --from=imports --to=requirements.txt </code></pre> <h1 id="実施手順"><a href="#%E5%AE%9F%E6%96%BD%E6%89%8B%E9%A0%86">実施手順</a></h1> <p>下記プロジェクトを例に説明します。</p> <p><a target="_blank" rel="nofollow noopener" href="https://github.com/515hikaru/create-requirement-from-imports">515hikaru/create-requirement-from-imports</a></p> <p>上記リポジトリにはサンプルとして<a target="_blank" rel="nofollow noopener" href="https://github.com/515hikaru/create-requirement-from-imports/blob/master/notebook/load_data.ipynb">僕がなんとなく書いた</a>ノートブックが置いてあります。このサンプルでは下記のように import をしています。</p> <ul> <li>先頭のセルで pandas の import</li> <li>関数内で matplotlib の import(動的インポート)</li> <li>ノートの後半で PyTorch(torch)と sklearn の import</li> </ul> <p>もちろん(?)プロジェクトには requirements.txt もなんにもありません。この状態から、requirements.txt を作ります。</p> <h2 id="DepHell のインストール"><a href="#DepHell+%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">DepHell のインストール</a></h2> <p>まずはコマンドをインストールしましょう。Python3.6 以上が必要です。公式のインストール方法に従います。</p> <pre><code>curl -L dephell.org/install | python3 </code></pre> <p>ちなみに現時点では Windows はサポートできていないようです<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。</p> <h2 id="Jupyter Notebook をスクリプトに変換"><a href="#Jupyter+Notebook+%E3%82%92%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%AB%E5%A4%89%E6%8F%9B">Jupyter Notebook をスクリプトに変換</a></h2> <p>.ipynb ファイルは <code>jupyter nbconvert</code> コマンドで Python スクリプト形式に変換できます。もちろん、ブラウザでダウンロードする方法もありますが、たくさんノートブックがあるときはコマンドの方が楽に変換できるでしょう。</p> <pre><code>$ jupyter nbconvert --to script notebook/load_data.ipynb </code></pre> <p>これで notebook/load_data.py ができるはずです。</p> <h2 id="いざ変換"><a href="#%E3%81%84%E3%81%96%E5%A4%89%E6%8F%9B">いざ変換</a></h2> <p>変換する前に、Python のパッケージであることを示すために <code>__init__.py</code> を置く必要があります。</p> <pre><code>$ touch notebook/__init__.py </code></pre> <p>あとは変換コマンドを実行するだけです。</p> <pre><code>$ dephell deps convert --from imports --to requirements.txt $ cat requirements.txt matplotlib pandas scikit-learn torch </code></pre> <p>ノートブックに登場していたすべての外部パッケージがリストアップされました。</p> <p>あとはバージョンを固定するなり、このままリポジトリに add するなり、好きにしましょう。</p> <h1 id="終わりに"><a href="#%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%AB">終わりに</a></h1> <p>サンプルはたった 4 つだったので手動でやってもたかが知れていますが、実際の現場では複数のモジュールを使っていたりしてあとから全容を把握するのは結構大変ということはあると思います。</p> <p>DepHell が依存関係の記述の一助になれば幸いです。</p> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p>ほとんどの場合、ノートは 1 つではなく複数でしょう。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> <li id="fn:2" role="doc-endnote"> <p>https://github.com/dephell/dephell/issues/343 <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> 515hikaru