PyInstallerを使用してPython実行可能ファイルを作成する方法

Pythonは、それ自体が強力で用途が広いため、すぐに使用できるいくつかの重要な機能がありません。1つは、Pythonは、Pythonプログラムをスタンドアロンの実行可能パッケージにコンパイルするためのネイティブメカニズムを提供していません。

公平を期すために、Pythonの元のユースケースでは、スタンドアロンパッケージが必要になることはありませんでした。Pythonプログラムは、概して、Pythonインタープリターのコピーが存在するシステム上でインプレースで実行されてきました。しかし、Pythonの人気が急上昇しているため、PythonランタイムがインストールされていないシステムでPythonアプリを実行する必要性が高まっています。

いくつかのサードパーティは、スタンドアロンのPythonアプリをデプロイするためのソリューションを設計しています。束の中で最も人気のあるソリューションであり、最も成熟しているのはPyInstallerです。PyInstallerは、Pythonアプリをパッケージ化するプロセスを完全に無痛にするわけではありませんが、それは大いに役立ちます。

この記事では、PyInstallerの動作方法、PyInstallerを使用してスタンドアロンのPython実行可能ファイルを作成する方法、作成するPython実行可能ファイルを微調整する方法、よくある落とし穴を回避する方法など、PyInstallerの使用の基本について説明します。 PyInstallerを使用して。

PyInstallerパッケージの作成

PyInstallerはPythonパッケージであり、pippip install pyinstaller)とともにインストールされます。PyInstallerはデフォルトのPythonインストールにインストールできますが、パッケージ化するプロジェクトの仮想環境を作成し、そこにPyInstallerをインストールすることをお勧めします。

PyInstallerは、Pythonプログラムを読み取り、それが行うすべてのインポートを分析し、それらのインポートのコピーをプログラムにバンドルすることで機能します。PyInstallerは、エントリポイントからプログラムを読み込みます。たとえば、プログラムのエントリポイントがmyapp.pyである場合pyinstaller myapp.py、分析を実行するために実行します。PyInstallerは、NumPyなどの多くの一般的なPythonパッケージを検出して自動的にパッケージ化できますが、場合によってはヒントを提供する必要があります。(これについては後で詳しく説明します。)

コードを分析し、使用するすべてのライブラリとモジュールを検出した後、PyInstallerは「スペックファイル」を生成します。拡張子が付いたPythonスクリプト.spec。このファイルには、Pythonアプリをどのようにパックする必要があるかについての詳細が含まれています。アプリで初めてPyInstallerを実行すると、PyInstallerはスペックファイルを最初から生成し、いくつかの適切なデフォルトを設定します。このファイルを破棄しないでください。これは、PyInstallerの展開を改善するための鍵です。

最後に、PyInstallerは、すべての依存関係にバンドルされた実行可能ファイルをアプリから生成しようとします。完了すると、dist (デフォルトでは、別の名前を自由に指定できます)という名前のサブフォルダーがプロジェクトディレクトリに表示されます。これには、バンドルされたアプリであるディレクトリが含まれています。このディレクトリには、.exe実行するファイルと、必要なすべてのライブラリおよびその他の補足ファイルが含まれています。

プログラムを配布するために必要なのは、このディレクトリを.zipファイルまたはその他のバンドルとしてパッケージ化することだけです。バンドルは通常、実行するためにユーザーが書き込み権限を持っているディレクトリに抽出する必要があります。

PyInstallerパッケージのテスト

PyInstallerを使用してアプリをパッケージ化する最初の試みが完全に成功しない可能性は十分にあります。

PyInstallerパッケージが機能するかどうかを確認するには、バンドルされている実行可能ファイルを含むディレクトリに移動し.exe、コマンドラインからファイルを実行します。実行に失敗した場合、コマンドラインに出力されるエラーは、何が問題であるかについてのヒントを提供するはずです。

PyInstallerパッケージが失敗する最も一般的な理由は、PyInstallerが必要なファイルをバンドルできなかったことです。このような欠落しているファイルは、いくつかのカテゴリに分類されます。

  • インポートの非表示または欠落:通常、動的にインポートされるため、PyInstallerがパッケージまたはライブラリのインポートを検出できない場合があります。パッケージまたはライブラリは手動で指定する必要があります。
  • スタンドアロンファイルがない:プログラムが、プログラムにバンドルする必要のある外部データファイルに依存している場合、PyInstallerにはそれを知る方法がありません。ファイルを手動で含める必要があります。
  • 不足しているバイナリ:ここでも、プログラムが.DLLなどの外部バイナリに依存していてPyInstallerが検出できない場合は、手動で含める必要があります。

良いニュースは、PyInstallerが上記の問題に対処する簡単な方法を提供することです。.specpyInstallerのによって作成されたファイルには、我々はpyInstallerのは逃した詳細を提供するために記入できるフィールドが含まれています。

.specテキストエディタでファイルを開き、Analysisオブジェクトの定義を探します。渡されるパラメーターのいくつかAnalysisは空白のリストですが、不足している詳細を指定するために編集できます。

  • hiddenimports非表示または欠落しているインポートの場合:このリストに、アプリに含めるライブラリの名前を含む1つ以上の文字列を追加します。あなたが追加したい場合pandasbokeh、例えば、あなたがそのように指定します ['pandas','bokeh']。問題のライブラリは、PyInstallerを実行しているPythonの同じインスタンスにインストールする必要があることに注意してください。
  • datasスタンドアロンファイルが欠落している場合:プロジェクトに含めるプロジェクトツリー内のファイルの仕様を1つ以上ここに追加します。各ファイルは、プロジェクトディレクトリ内のファイルへの相対パスと、ファイルを配置する配布ディレクトリ内の相対パスを示すタプルとして渡す必要があります。たとえば./models/mainmodel.dat、アプリに含めたいファイルがあり、それを配布ディレクトリ内の一致するサブディレクトリに配置する場合は('./models/mainmodel.dat','./models')hiddenimportsリストの1つのエントリとして使用します。globスタイルのワイルドカードを使用して、複数のファイルを指定できることに注意してください。
  • binariesスタンドアロンバイナリが欠落しているdatas場合:と同様に、を使用binariesして、プロジェクトツリー内のバイナリの場所と配布ディレクトリ内の宛先を指定するタプルのリストを渡すことができます。ここでも、globスタイルのワイルドカードを使用できます。

渡されるリストはすべてAnalysis.specファイルの前半でプログラムによって生成できることに注意してください。結局のところ、.specファイルは別の名前のPythonスクリプトにすぎません。

.specファイルに変更を加えた後、PyInstallerを再実行してパッケージを再構築します。ただし、今後は、変更した.specファイルを必ずパラメータとして渡してください(例pyinstaller myapp.spec)。前と同じように実行可能ファイルをテストします。それでも何かが壊れている場合は、.specファイルを再編集して、すべてが機能するまでプロセスを繰り返すことができます。

最後に、すべてが意図したとおりに.spec機能することを確認したら、ファイルを編集して 、パッケージ化されたアプリが起動時にコマンドラインウィンドウを表示しないようにすることができます。ファイルEXE内のオブジェクト設定で、を設定し.specます console=False。コンソールの抑制は、アプリにGUIがあり、ユーザーを迷わせるような偽のコマンドラインウィンドウが必要ない場合に役立ちます。もちろん、アプリでコマンドラインが必要な場合は、この設定を変更しないでください。

PyInstallerパッケージの改良

アプリをPyInstallerにパッケージ化して適切に実行したら、次に実行したいことは、アプリを少しスリム化することです。PyInstallerパッケージは洗練されていることで知られていません。

Pythonは動的言語であるため、特定のプログラムが実行時に何を必要とするかを予測することは困難です。そのため、PyInstallerがパッケージのインポートを検出すると、プログラムによって実行時に実際に使用されているかどうかに関係なく、そのパッケージ内のすべてが含まれます。 

これが朗報です。PyInstallerには、パッケージ全体、またはパッケージ内の個々の名前空間を選択的に除外するメカニズムが含まれています。たとえば、プログラムfoofoo.barとを含むパッケージをインポートするとしますfoo.bip。プログラムがのロ​​ジックのみを使用していることがわかっている場合はfoo.bar、安全に除外foo.bip してスペースを節約できます。

これを行うには、ファイル内のオブジェクトにexcludes渡されたパラメーターを使用Analysis.specます。名前のリスト(トップレベルモジュール、または点線の名前空間)を渡して、パッケージから除外することができます。たとえば、を除外するにはfoo.bip、単にを指定します ['foo.bip']

一般的に除外できるのはtkinter、単純なクロスプラットフォームのグラフィカルユーザーインターフェイスを作成するためのPythonライブラリです。デフォルトで tkinterは、そのすべてのサポートファイルはPyInstallerプロジェクトにパックされています。tkinterプロジェクトで使用していない場合は'tkinter'excludesリストに追加して除外できます。省略tkinterすると、パッケージのサイズが約7MB小さくなります。

もう1つの一般的な除外は、テストスイートです。プログラムがインポートするパッケージにテストスイートが含まれている場合、テストスイートがPyInstallerパッケージに含まれる可能性があります。デプロイされたプログラムで実際にテストスイートを実行しない限り、安全に除外できます。

除外を使用して作成されたパッケージは、使用する前に徹底的にテストする必要があることに注意してください。予期していなかった将来のシナリオで使用される機能を除外することになった場合、アプリは壊れます。

PyInstallerのヒント

  • デプロイする予定のOSでPyInstallerパッケージをビルドします。 PyInstallerはクロスプラットフォームビルドをサポートしていません。スタンドアロンのPythonアプリをMacOS、Linux、およびWindowsシステムにデプロイする必要がある場合は、PyInstallerをインストールし、これらの各オペレーティングシステムでアプリの個別のバージョンをビルドする必要があります。 
  • アプリを開発しながら、PyInstallerパッケージをビルドします。  PyInstallerを使用してプロジェクトをデプロイすることがわかったらすぐに、.specファイルをビルドし、アプリの開発と並行してPyInstallerパッケージの改良を開始します。このようにして、除外または包含を追加し、作成時にアプリで新しい機能が展開される方法をテストできます。
  • PyInstallerの--onefileモードを使用しないで ください。  PyInstallerには、--onefileアプリ全体を単一の自己解凍型実行可能ファイルにパックするコマンドラインスイッチが含まれています。これは素晴らしいアイデアのように思えます—ファイルを1つだけ配信する必要があります! —しかし、いくつかの落とし穴があります。アプリを実行するときは常に、最初に実行可能ファイル内のすべてのファイルを一時ディレクトリに解凍する必要があります。アプリが大きい場合(たとえば200MB)、解凍すると数秒の遅延が発生する可能性があります。代わりに、デフォルトの単一ディレクトリモードを使用し、すべてを.zipファイルとしてパックします。
  • PyInstallerアプリのインストーラーを作成します。 .zipファイル以外の方法でアプリをデプロイする場合は、オープンソースのNullsoft Scriptable InstallSystemなどのインストーラーユーティリティの使用を検討してください。成果物のサイズにオーバーヘッドをほとんど追加せず、実行可能ファイルへのショートカットの作成など、インストールプロセスの多くの側面を構成できます。
  • スピードアップを期待しないでください。 PyInstallerは パッケージングシステムであり、コンパイラ や オプティマイザではありません 。PyInstallerにパッケージ化されたコードは、元のシステムで実行した場合よりも速く実行されません。Pythonコードを高速化したい場合は、タスクに適したCアクセラレーションライブラリ、またはCythonのようなプロジェクトを使用してください。

Pythonでさらに多くのことを行う方法

  • Cythonチュートリアル:Pythonを高速化する方法
  • Pythonをスマートにインストールする方法
  • PoetryによるPythonプロジェクト管理の改善
  • Virtualenvとvenv:Python仮想環境の説明
  • Pythonvirtualenvとvenvはすべきこととすべきでないこと
  • Pythonのスレッド化とサブプロセスの説明
  • Pythonデバッガーの使用方法
  • timeitを使用してPythonコードをプロファイリングする方法
  • cProfileを使用してPythonコードをプロファイリングする方法
  • Pythonで非同期を始めましょう
  • Pythonでasyncioを使用する方法
  • PythonをJavaScriptに変換する方法(そしてまた元に戻す方法)