この記事はこんな方におすすめです
- Macで `No module named ‘_tkinter’` というエラーが出ている方
- AnacondaではTkinterが使えたのに、pyenvやvenvの環境では使えず困っている方
- Pythonの環境構築中に「Xcodeが古い」と表示され、戸惑っている方
- Python・仮想環境・Command Line Toolsの関係を、実例を通して知りたい方
今回の環境と、この記事の対象
- macOS:14.1.1
- Python:3.11.15(pyenvで管理)
- pyenv:2.8.2
- 仮想環境:プロジェクト内の
.venv - 確認できたCommand Line Tools:15.3
- 用意したTcl/Tk:
tcl-tk@88.6.18
※この記事は、私の環境で解決できた記録です。Homebrew版PythonやAnacondaでは対応が異なります。同じエラーでも、原因や必要な開発ツールは環境によって変わります。
最初のエラー:No module named ‘_tkinter’
最初に実行しようとしたのは、ウィンドウを表示するだけのコードです。
import tkinter as tk
window = tk.Tk()
window.title("勤怠アプリ")
window.geometry("480x640")
window.mainloop()
これを main.py として保存し、仮想環境を有効にして起動しました。
source .venv/bin/activate
python main.py
すると、次のエラーが出ました。
ModuleNotFoundError: No module named '_tkinter'
tkinter と _tkinter は少し役割が違います。Pythonのコードから使う入り口が tkinter、その裏側でTcl/Tkという画面表示の仕組みにつなぐ部品が _tkinter です。今回は後者が使えない状態でした。
TkinterはPythonの標準ライブラリですが、Pythonのインストール方法や、作られたときの環境によっては、この部品が含まれていないことがあります。
venvを有効にしたのに、別の場所のPythonを見ている?
エラーには、プロジェクトの .venv ではなく、次のような場所が表示されていました。個人名の部分は省略しています。
~/.pyenv/versions/3.11.15/lib/python3.11/tkinter/__init__.py
「仮想環境を有効にしたはずなのに?」と思いましたが、venvは元になるPythonを利用する仕組みなので、標準ライブラリの場所が .venv の外でも、それだけで異常とは限りません。
実行中のPythonと、その元になったPythonは、次のコマンドで確認できます。
python -c "import sys; print('実行中:', sys.executable); print('元のPython:', sys.base_prefix)"
AnacondaでTkinterが使えていたのも、今回のpyenvとは別のPython環境だったためです。別の環境で使えるライブラリが、今の環境でも使えるとは限らないのですね。
途中で「Xcodeが古い」という別のエラーも出た
Tcl/Tkを用意する過程で、Homebrewの python-tk@3.11 もインストールしようとしました。しかし、Xcode 14.3.1が古く、16.2への更新を求めるエラーが出て止まってしまいました。
ただ、あとから整理すると、python-tk@3.11 はHomebrew版Python向けのパッケージです。今回直したかったのはpyenv版のPythonなので、このインストールを通すことが解決の必須条件ではありませんでした。
そこで、Xcode本体を更新する前に、使用中の開発ツールを確認しました。
xcode-select -p
確認時の結果はこちらです。
/Library/Developer/CommandLineTools
バージョン情報も確認しました。
pkgutil --pkg-info=com.apple.pkg.CLTools_Executables
この環境には、Command Line Tools 15.3が入っていました。
XcodeはAppleのアプリ開発用の道具一式です。一方、Command Line Toolsは、ターミナルで開発するためのコンパイラーなどをまとめたもので、Xcode本体とは別にインストールできます。
今回は、Xcode本体を更新せずに、既存のCommand Line Toolsを使ってPythonを作れました。ただし、これは「古いXcodeがあっても、どんなPythonでも必ず作れる」という意味ではありません。作りたいPythonと、macOS・開発ツールの組み合わせによって結果は変わります。
解決手順① Tcl/Tk 8を用意する
ここからは、解決に使った手順を順番に整理します。コマンドはターミナルで実行します。
brew install tcl-tk@8
私の環境には最初、Tcl/Tk 9が入っていました。今回はPython 3.11.15で使うためにTcl/Tk 8を追加しました。
インストール状況は、次のコマンドで確認できます。
brew list --versions tcl-tk@8
ただし、Tcl/Tkを後から入れただけでは、すでにインストールされているPythonに不足していた部品が追加されるわけではありません。 続いてPythonを作り直します。
解決手順② 同じPythonを別の名前で作り直す
ターミナルの先頭に (.venv) が付いている場合は、いったん仮想環境を解除します。
deactivate
元のPythonは残し、Tkinter用に別の名前でインストールしました。以下は、使うTcl/Tkを明示する設定も含めたコマンドです。
PYTHON_BUILD_HOMEBREW_TCLTK_FORMULA=tcl-tk@8 \
pyenv install 3.11.15:3.11.15-tk
1行目でHomebrewの tcl-tk@8 を指定しています。行末の \ は、コマンドが次の行に続くという意味です。2行をまとめて実行します。
3.11.15:3.11.15-tk は、「Python 3.11.15を、3.11.15-tkという名前でインストールする」という指定です。末尾の -tk は区別のための名前で、正式なバージョン番号ではありません。
私の場合、ログに次の表示がありました。
python-build: use tcl-tk@8 from homebrew
その後、3.11.15-tk へのインストールが完了しました。Python自体を新しいバージョンにしたのではなく、同じ3.11.15を、Tkinterが使える構成で作り直したことになります。
解決手順③ 新しいPythonでウィンドウを確認する
まずは仮想環境を作り直す前に、新しく用意したPythonを直接指定して確認しました。
"$(pyenv root)/versions/3.11.15-tk/bin/python" -m tkinter
$(pyenv root) は、pyenvの保存場所を取得する部分です。-m tkinter は、Tkinterの確認用プログラムを実行する指定です。
このコマンドで、小さな確認用ウィンドウが開きました! インストールのコマンドだけではウィンドウは開かないので、この確認は別に行います。
解決手順④ プロジェクトのvenvを作り直す
新しいPythonで動いても、既存の .venv は以前のPythonを元に作られたままです。source .venv/bin/activate だけでは、新しいPythonに切り替わりません。
ここからは、main.py と .venv があるプロジェクトのフォルダで作業します。仮想環境が有効なら、先に deactivate を実行します。
すでにライブラリを入れている場合は、作り直す前に一覧を控えておくと再インストールに役立ちます。次は任意の追加手順です。
.venv/bin/python -m pip freeze > requirements-before-rebuild.txt
古い仮想環境は、すぐに消さずに名前を変えて残しました。.venv-backup がすでにある場合は、別の未使用の名前にしてください。
mv .venv .venv-backup
Gitで管理している場合は、バックアップも公開しないように .gitignore に追加しておきます。
.venv/
.venv-backup/
次に、Tkinterが使えるPythonを明示して、新しい仮想環境を作ります。
"$(pyenv root)/versions/3.11.15-tk/bin/python" -m venv .venv
新しい仮想環境を有効にします。
source .venv/bin/activate
元のPythonを確認すると、パスの末尾が 3.11.15-tk になっていました。
python -c "import sys; print('実行中:', sys.executable); print('元のPython:', sys.base_prefix)"
新しい仮想環境には、古い環境の追加ライブラリは引き継がれません。今回の最小コードはTkinterだけなので追加インストール不要でしたが、ほかのライブラリを使っているアプリなら再インストールします。一覧を保存した場合は、内容を確認してから次のように利用できます。
python -m pip install -r requirements-before-rebuild.txt
最後に、仮想環境の中で確認してからアプリを起動します。確認用ウィンドウを閉じたあと、次のコマンドへ進みます。
python -m tkinter
python main.py
これで、勤怠アプリのウィンドウも無事に表示できました。
必要なライブラリやアプリの動作を確認できたら、古い .venv-backup は削除できます。私はエディターのファイル一覧から削除しました。今使っている .venv と間違えないようにします。
なお、名前を変えた仮想環境は、そのまま別名で動かすためのものではなく、今回は復旧用に退避したものです。main.py などの自分のコードは、仮想環境のフォルダ内には置かないようにします。
今回分かったこと
最初は「Macが古いから、もうTkinterは使えないのかな」と思いました。でも、今回直接困っていたのは、使っているPythonに必要な部品が入っていなかったことでした。
解決までには、Python、pyenv、venv、Tcl/Tk、Xcode、Command Line Toolsと、いろいろな名前が出てきました。正直、一度で全部理解するのは難しいです。笑
それでも、「どのPythonで動かしているのか」と「そのPythonで作った仮想環境なのか」を確認することが大事だと分かりました。
この作業を、アプリを起動するたびに繰り返す必要はありません。これからはプロジェクトのフォルダで、いつもの2つのコマンドで進められます。
source .venv/bin/activate
python main.py
ようやく、勤怠アプリの画面づくりに進めそうです!