cx_Freeze + virtualenv =バグとジグザグ

先日、焼きたてのTelegramボットを実行可能ファイルにアセンブルすることにしました。 py2exepyInstallercx_Freezeなど 、さまざまなソリューションがあります。 私は自分のコンピューターとサーバーの両方でUbuntu 14.04を使用しています。そのため、クロスプラットフォームの性質Python 3のサポートにより、 cx_Freezeを選択しました。 (執筆時点では、同じプロパティを持つpyInstaller試す時間はありませんでした。何か面白いことがあれば、別の記事で説明します)。

cx_Freezeの設定


最初は、すべてがつまらないように見えました。
sudo apt install cx-freeze

Python2にcx_Freezeを設定するため、適切ではありません。

pip3を試してみましょう。
sudo pip3 install cx_Freeze

ただし、どのように。 Ubuntで(他のOSをまだ試していません)、これにより次のエラーが発生します(写真についてお。び申し上げます。執筆時点では、「これは長い話です」というシリーズの理由でテキストコピーペーストを作成することは困難でした):

画像

StackExchangeを調べたところ、 ソースからインストールしない物事が機能しないことに気付きました。

ダウンロードしました。 開梱。 立ち上げ:
sudo python3 setup.pyインストール

話は似ています:

画像

StackOverflowを再度調べました。 私はsetup.pyに入り 、そこで行を置き換える必要がありました:

if not vars.get("Py_ENABLE_SHARED", 0): 



 if True: 

私は再び起動しようとしました-それはインストールされました! やった!

ご注意

この記事を書いている間、Ubuntu 14.04 32ビットの「新しい」仮想マシンでインストールプロセスを繰り返しました。 私はエラーに遭遇しました:
/ usr / bin / ld:-lzが見つかりません

これによれば、以下を使用して解決されます(32ビットシステム)。
sudo apt-get install lib32z1-dev

念のため( この質問で言及されているので)、私はpython-devをインストールしました:
sudo apt-get install python-dev

スクリプトをまとめる!


cx_Freezeを使用してスクリプトを構築する最も簡単な方法を検討してください。 スクリプトフォルダーに移動して実行します。
cxfreeze main.py --target-dirビルド

ここで、 main.pyはメイン(実行)スクリプトの名前、 buildは実行可能ファイルとライブラリが保存されるフォルダーです。

C ++コンパイラとは異なり、cx_Freezeはエラーをキャッチしないことに注意してください。 したがって、すべてを完全に収集できますが、実行可能ファイルが起動されると、例外が散らばり、かなり読みにくい形式になります。 まだPythonicである間にコードをテストすることをお勧めします。

実行中のファイルにアセンブルするためのコードを最適化することは、Pythonインタープリターを介してスクリプトを実行するときに存在しなかった問題がアセンブリ中に発生する可能性があるため、別の議論のトピックだと思います。 ここで、そのような問題(神に感謝します。もう発生しませんでした)について説明します。

私のスクリプトは外部設定ファイルにアクセスします。 しかし、実行可能ファイルから開始するとき、何らかの理由で、スクリプトの名前を設定ファイルへのパス上のフォルダーの1つとして認識し始めました。 つまり、 mainという名前のアセンブルされた実行可能ファイルが/ tmp / 001にあり、設定ファイルが/ tmp / 001 / settにある場合、スクリプトは設定ファイルが実際に/ tmp / 001 / main / settにあると判断しました。 もちろん、これはナンセンスです。 しかし、Pythonスクリプトを実行する場合、これは問題ではありません。

実際のところ、私のプログラムの最初に次の行を詰め込むことがよくあります。

 SCRIPT_FOLDER = path.dirname(path.realpath(__file__)) 

次に、スクリプトに対して常に同じ場所にあるファイルへのパスを設定するときに、この変数を使用します。設定ファイル、保存、トークン、アプリケーションコードなど。したがって、プログラムが正しい場所からファイルを読み取ることを保証します。起動場所に関係なく(たとえば、別のフォルダから、またはデーモンを介して)。

cx_Freezeで収集されたスクリプトは、通常、__ file__グローバル変数を誤って解釈するか、まったく知らないかのいずれかです。 後者は、単純なテストスクリプトから実行可能ファイルをコンパイルして実行しようとしたときに発生しました。

 from os import path SCRIPT_FOLDER = path.dirname(path.realpath(__file__)) print(SCRIPT_FOLDER) 

問題はわかっていることがわかった 。 プログラムに少しパッチをあてれば十分でした:

 if getattr(sys, 'frozen', False): # frozen SCRIPT_FOLDER = path.dirname(sys.executable) else: SCRIPT_FOLDER = path.dirname(path.realpath(__file__)) 

その結果、すべてがハーフキックで始まりました! 素晴らしい。 簡単な部分は完了です! これをすべて仮想環境で繰り返しましょう!

ああ、これらの仮想環境!


virtualenvを使用しない場合、この記事をこれ以上読むことにあまり興味がないと思います。 その特徴は、環境にcx_Freezeをインストールするだけでなく、システムの依存関係ではなく、環境の依存関係を使用するように起動することにもあります。

ご注意

シェルで環境を使用する必要はありません(「source env / bin / activate」から起動されます)。 試しましたが、効果はありませんでした。

設置


私の仮想環境は、プロジェクトのメインディレクトリのenvフォルダーにあります。 cx_Freezeを環境にインストールするには、cx_Freezeソースフォルダーに移動し(上記の方法で処理されたsetup.pyファイルを使用)、次を実行します。
/パス/ to / my / project / env / bin / python3 setup.py install

あまり便利ではありません。 途中でPythonインタープリターへのパスを規定する必要がありました。 しかし、すべてが解決しました。

組立


上記の1行の方法はここでは機能しません。 あなたは別のものを使用する必要があります-インストールファイルを通して。

このファイルは、私にとっては十分な短い形式で、次のようになります。

 from cx_Freeze import setup, Executable PROGRAM_NAME = "Train delays bot" VERSION = "0.0.5" MAIN_SCRIPT_NAME = "train_delays_bot_main.py" setup( name = PROGRAM_NAME, version = VERSION, executables = [Executable(MAIN_SCRIPT_NAME)]) 

ここで最も重要なことは、プログラムのメインファイルの名前に対応するMAIN_SCRIPT_NAMEを設定することです。

このスクリプトをプロジェクトフォルダに入れてそこに行きます。 以下を開始します。
env / bin / python3 setup.py install

ビルドフォルダーは自動的に作成され、その中に別のexe.linux-x86_64-3.4が作成されました(お使いの場合、OSとインタープリターのバージョンによって異なる呼び出しが行われる場合があります)。 実行可能ファイルとライブラリが含まれています。 トークンと設定ファイルを含むフォルダーをそこに移動しました。 それはすべて始まりました。 そして、依存バージョンは仮想環境からのものであることが判明しました。 特に2時間のハードワークの後、これは朗報です。

結論として


そして免責事項の代わりに。 絶対に正しいふりをして、上記の方法の利便性を最大限に高めるつもりはありません。 より効果的な方法がある場合は、コメントでそれらについて教えてください。 私の執筆をマスターした誰もが興味を持っていると思います。

Source: https://habr.com/ru/post/J282359/


All Articles