こんにちは、Tech Samuraiです!
最近の私のPython開発環境では、モダンなプロジェクト管理ツール「Rye」が不動の相棒となっています。しかし先日、Jetson(NVIDIA製の小型コンピュータ)上でRye環境を構築し、データ可視化の王道ライブラリ`Matplotlib`を使おうとした際、思わぬ大きな壁にぶつかりました。
それは、**`plt.show()`でグラフを画面に表示しようとしても、何も表示されず、奇妙な警告が出る**という問題です。今回の記事は、この問題を解決するために私が行った、試行錯誤の全プロセスを記録した、リアルなトラブルシューティングの物語です。同じ壁にぶつかった誰かのための、そして問題解決の思考プロセスを共有するための、航海日誌です。
発端:目標と最初の壁
まず、私の目標はシンプルでした。「Jetson上でRyeを使い、Matplotlibで作成したグラフをインタラクティブに画面表示(`plt.show()`)したい」。しかし、実際にスクリプトを実行すると、現実は甘くありませんでした。
# 実行コマンド
rye run python my_plot_script.py
グラフウィンドウは表示されず、ターミナルには以下のような警告が。
UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown
これは、「Matplotlibが非インタラクティブなAggというモードで動いているので、画面表示はできませんよ」という意味です。Ryeが作る隔離された仮想環境が、GUIの情報をうまく引き継げていないのだろう、とこの時は軽く考えていました。ひとまず`plt.savefig()`で画像として保存すれば結果は確認できましたが、目標であるインタラクティブな表示は達成できません。
試行錯誤の道のり – 犯人探しの探偵劇
ここから、原因を特定するための長い戦いが始まりました。
フェーズ1:DISPLAY環境変数の受け渡し
仮説: GUIの「住所」である`DISPLAY`環境変数が、Ryeの環境に伝わっていないのでは?
試したこと: OSの`DISPLAY`変数を引き継いでコマンドを実行。
DISPLAY=$DISPLAY rye run python my_plot_script.py
結果: 失敗。状況は全く変わらず、同じ警告が表示されました。住所を伝えるだけでは不十分で、描画するための「画材(ライブラリ)」自体が環境内にない可能性が浮上しました。
フェーズ2:GUIツールキット(Tkinter)の確認
仮説: Matplotlibが使うGUIの画材である`Tkinter`が、OSにインストールされていないのでは?
試したこと: `Tkinter`のパッケージである`python3-tk`をインストール。
sudo apt install python3-tk
結果: 失敗。「すでに最新版がインストールされています」と表示され、状況は変わりませんでした。OSには画材があるのに、なぜRyeの環境内からだけ見えないのか?Ryeが作る仮想環境の**強すぎる隔離性**が原因だと、徐々に核心に近づいていきました。
フェーズ3:根本原因の特定
仮説: ならば、スクリプト側から強制的に「Tkinterを使いなさい」と命令したらどうなる?
試したこと: Pythonコードの冒頭で、バックエンドを明示的に指定。
import matplotlib
matplotlib.use('TkAgg') # Tkinterを使うよう強制
import matplotlib.pyplot as plt
結果: ついに犯人が姿を現しました。曖昧な「警告」が、以下のような**致命的な「エラー」**に変わったのです。
ImportError: ... python-build-standalone, which is not compatible with Tk
根本原因の判明: このエラーメッセージが全てを物語っていました。Ryeが私のJetsonのために自動でダウンロードしてくれたPython(`python-build-standalone`)は、**GUI機能(Tk)を含まないようにビルドされた、軽量なサーバー向けバージョンだった**のです。どんなに外部から設定しても、Python自体にその機能がコンパイルされていなければ、使えるはずがありませんでした。
最終的な解決策:Ryeに「システム標準のPython」を使わせる
原因が分かれば、解決策はシンプルです。Ryeが持ってきたGUI機能なしのPythonを使うのをやめ、**OSにもともとインストールされているGUI機能ありのPython(`python3-tk`を認識できるもの)を、Ryeの管理下で使う**という方針に転換しました。
- OSのPythonをRyeに登録する
まず、GUIが使えるPythonのフルパスを`which`コマンドで調べ、それをRyeの`toolchain`(ツール群)に登録します。# GUIが使えるPythonのフルパスを調べる (例: /usr/bin/python3.10) which python3.10 # 調べたパスをRyeに登録する rye toolchain register /usr/bin/python3.10
- プロジェクトで使うPythonを指定する
`rye pin`コマンドで、今登録した「システム標準のPython」を使うように、名前を明示して指定します。(Ryeが認識した名前は`rye toolchain list`で確認できます)# Ryeが認識した名前(例: cpython@3.10.12)を指定 rye pin cpython@3.10.12
- 環境の再構築と実行
新しいPython設定に基づいて仮想環境を再構築し、フェーズ1で試した`DISPLAY`変数を渡す方法で、再度実行します。rye sync DISPLAY=$DISPLAY rye run python my_plot_script.py
すると、ついに…!Jetsonの画面に、Matplotlibのグラフウィンドウが、インタラクティブな形で表示されたのです!
まとめ:今回の冒険からの教訓
この長いトラブルシューティングの旅から、以下の重要な教訓を得ました。
- Ryeが提供するPythonは、デフォルトではGUIプログラミングを想定していないサーバー向けビルドの可能性がある。
rye run
の隔離された環境でGUIを扱うには、描画先を教える「`DISPLAY`環境変数」と、描画能力を持つ「GUI機能付きPython本体」の両方が必要。- Ryeの
toolchain register
機能は非常に強力で、システムのPythonと連携させることで、Ryeの利便性とシステムの機能を両立できる。
エラーはプログラマーの友です。一つ一つの仮説検証が、私たちをシステムのより深い理解へと導いてくれます。この記録が、あなたの問題解決のヒントになれば幸いです!
コメント