C++ feat. Python 簡単に接続、埋め込み、インストール
C++ feat. Python Easy connection, embedding, installation
C++エンタープライズアプリケーションはWindowsでPythonモジュールを実行します。このテックフュージョンのプロセスをコードの最初の行からアプリケーションの配信までの旅としてご紹介します。
イントロ
Pythonのシンプルさ、包括的なパッケージエコシステム、サポートのあるコミュニティは魅力的な選択肢です。一方、複雑なユーザーインターフェース、マルチスレッドのデータフロー、エンタープライズソリューションの24時間の堅牢性を扱う場合、C++が主役となります。時には、これらの2つを融合させ、両方の世界の利点を得ることを目指す必要があります。
よくあるケースでは、Pythonコードが複雑なアルゴリズムの計算のためにC++のメソッドを呼び出します。しかし、私は逆のシナリオに遭遇しました。機械学習アプリケーションでPythonベースの推論コードを使用してカスタムモデルを緊急に呼び出す必要がありました。それをC++で書き直すか、対応する推論エンジンを採用することは不可能でした。最初の考えはシンプルでした。「C++からPythonを呼び出すのは簡単なはずだ」と。しかし、私はその複雑さを過小評価していました!
期待と現実
C++とPythonの間の相互作用を容易にするいくつかの橋が利用可能です:
- 標準のPythonパッケージにバンドルされたC++ヘッダとライブラリ(Python.h、Python.lib)を介したPythonの組み込みC++インターフェース。
- Boostライブラリに慣れている場合は、Boost.Pythonを使用します。
- 私の好みであるPybind11は、パワーとプロジェクトへの統合の容易さのバランスが取れています。
一見すると、解決策は手の届く範囲にあり、この3つの中から最適な橋を選ぶだけです。しかし、もっと詳しく見てみましょう!
前述のメソッドは、Python-C++の通信を可能にするというコアな目的において優れています。これは初期の試行や実験に十分です。しかし、提供可能なソリューションを構築することを目指す場合、フルソフトウェアライフサイクルを考える必要があります。その中で解決する必要がある課題の一つは、配布です。はっきり言うと、C++バイナリをPythonコンポーネントと一緒に配布することです。Pythonコードそのものを共有することも難しい場合があります。さらに、複数のPythonバージョンが共存する可能性があり、追加のパッケージには依存関係の解決を含めた適切なインストールが必要です。問題は、私たちのケースではどのオプションが有効なのか、ということです。
- C++アプリケーションを利用する前に、ユーザーにPythonと必要なパッケージのインストールを指示する。
- C++インストーラにPythonインストーラを組み込み、関連する問題(ユーザーシステム上の他のPythonインストールなど)を自動的に解決する。
どちらも最適ではありません。そのため、より信頼性と安定性のあるアプローチを見つけるための探求を始めました。それを皆さんと共有できることを楽しみにしています。
埋め込みPython
Pythonのホームページを最後に訪れた時、配布オプションを探索しましたか?その中には魅力的な選択肢があります: Windows埋め込みパッケージ。このオプションは私の興味を引きました。配布の問題に対する魔法のような解決策を提供してくれるように見えます。公式ドキュメンテーションを掘り下げると、この埋め込みバージョンについての詳細が明らかになりました。驚くべきことに、Pythonは他のアプリケーションにシームレスに統合するための埋め込みバージョンを提供しています。
埋め込みバージョンのアーカイブの内容を調べると、いくつかの疑問が浮かび上がります。このセットアップに追加のモジュールをどのように追加できるのでしょうか?また、C++アプリケーションをこの埋め込みバリアントを利用するように指示する方法はありますか?
最初の質問に答えるのは比較的簡単です。パッケージは標準のPythonインストールから単にコピーするだけです。
2番目の質問は、前述のPythonブリッジがデフォルトのインストールと連携しているため、広範な調査を必要としました。Pythonの環境変数(PYTHONPATH、PYTHONHOME)を変更することはたまに役立つかもしれませんが、Pythonは異なるOSの場所にファイルを配置する場合がありますので、埋め込みセットアップに切り替えるための究極の解決策ではありません。
C++用のPythonフラグ
最もシンプルなPythonプログラムは1行だけです:
print(‘Hello, World!’)
この明らかなシンプルさを実現するために、Pythonは多くの内部ルーチンからプログラマを保護しています。この行を静かに実行する際には、インタプリタがインストールパラメータ、初期化、デフォルトのモジュールのインポート、バイトコードのコンパイル、関数の検索などを処理します。しかし、これらの秘密のメカニズムに介入する方法があります。公式ドキュメンテーションを引用すると、「Pythonには異なる機能とオプションを制御するためのグローバルな設定変数があります」とあります。これらはコマンドライン引数やフラグ、そしてC++コードからアクセス可能なフラグとメソッドとして存在します(すでに言及したPython.hを介してアクセスできます)。今回の場合、Py_SetPath()メソッドを使ってPythonの検索パスを上書きする必要があります。他のフラグはいくつかの特殊なケースで使われます: Py_NoSiteFlag、Py_NoUserSiteDirectory、Py_IgnoreEnvironmentFlag。これらのフラグは、デフォルトのモジュールサイトの読み込みをスキップしたり、ユーザーのホームディレクトリにモジュールがある別のディレクトリを無視したりするために使用します。特定のケースを処理するためにチェックしてみてください!
概要ガイド
- C++プロジェクトを準備してPythonを統合を開始します。
- Pythonのバージョンを決定し、デフォルトのインストール先としてWindowsにインストールします。
- 埋め込みパッケージとして同じバージョンのPythonをダウンロードし、プロジェクトディレクトリに展開します。
- 必要なPythonメソッドを呼び出すPythonテストコードを作成し、その後のモジュールのコピーとテストに使用します。
- 埋め込みインストールでPythonテストコードを起動します(検索パスを上書きするためにコマンドラインフラグを使用します)。デフォルトのモジュールが使用されていない場合、ミスしたモジュールをデフォルトのインストールから埋め込みインストールに1つずつコピーして、Pythonテストコードを正常に完了します。
- C++プロジェクトに移動します。 pybind11を取得します。検索パスを含むプロジェクトを追加します。
- デフォルトのPythonインストールからヘッダとライブラリの検索パスをプロジェクトに追加します。
- C++コードで Py_SetPath() を使用してPython埋め込みインストールへの相対パスを設定します。必要に応じて追加のフラグを使用します。
- Pythonパッケージの1つがユーザーサイトパッケージディレクトリにある場合は、それを埋め込みパッケージフォルダにコピーし、Py_SetPath() で別個のパスを追加します。
- C++コードで、pybind11 APIを使用してPythonメソッドにアクセスします。C++プログラムがPythonメソッドの呼び出しでフリーズする場合、おそらくいくつかのPythonモジュールをインポートできないため、ステップ [5]のPythonテストコードを使用して解決します。
- 埋め込みPythonフォルダを含めたC++バイナリを配布します。また、python3.dllやWindowsの再頒布パッケージなど、一部のDLLをバイナリの場所にコピーする必要がある場合もあります。
最終パート
本番用途のC++アプリケーションは、ユーザーが気づかないように埋め込みPythonをその一部として含めることができます。これは、私たちがインストールについて悩むよりも、シンプルでパワフルなアプリケーションの助けを借りてタスクを実行したいという希望に応える素晴らしい成果です!
この記事のすべての洞察を取り入れたデモプロジェクトを共有していますので、クイックスタートにご活用ください。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles