WSL + Homebrewの環境でMkDocsがModuleNotFoundError: No module named '_ctypes'
Markdownベースでドキュメントサイトを作ることができるPython製のツール MkDocs を使おうとしたところ、 ModuleNotFoundError
が発生してコマンドが動かない問題が出てしまいました。
原因はHomebrew (Linuxbrew)で入れていたライブラリで、それを除去してPythonを入れ直すことで解消したので、経緯をメモしておきます。
環境
エラーが出た状況と考察
WSL (Ubuntu)環境で、venvで作ったPython仮想環境に pip install mkdocs
でMkDocsをインストールしました。
インストール自体は問題なかったものの、 mkdocs new
を実行時にエラーが発生しました。
$ mkdocs new Traceback (most recent call last): ... ModuleNotFoundError: No module named '_ctypes'
参考になったのは Pythonでの ctype の依存関係エラー対策の備忘録 / ModuleNotFoundError: No module named ctypes 対策 | simple blog という記事でした。
WSL上にPythonをインストールするにあたり、asdfとそのプラグインであるasdf-pythonを使っています。
asdf-pythonの内部ではpyenvが使われており、pyenvはPythonのバージョンをインストールするときにソースコードからビルドをおこないますが、その際環境に応じて事前に必要なパッケージをインストールしておく必要があります。
そういえば、WSL上にPython環境を構築するとき、Homebrewも導入していたこともあり、一度Linuxbrew用の指定パッケージを入れてしまっていました。
ただ、これではうまくいかず、Ubuntu用の指定パッケージを入れることでasdf-pythonが使えるようになりました。
そのため、もしかするとこのときに入れてしまったLinuxbrew用のパッケージが影響しているのではないかと考えました。
Homebrew (Linuxbrew) の依存関係を取り除く
先のpyenvのサイトによると、Linuxbrewの場合は以下のパッケージが指定されています。
brew install bzip2 libffi libxml2 libxmlsec1 openssl readline sqlite xz zlib
よって、これらを削除すれば良いかなと思いましたが、Homebrewの他のアプリケーションなどで使われているものがあるかもしれないので、念のため調べてみます。
参考: Homebrew でパッケージの依存関係を調べる方法 - Qiita
brew uses <package> --installed
で、そのパッケージがインストールされている他のパッケージから使われているかどうかを調べることができるとのこと。
$ brew uses bzip2 --installed $ brew uses libffi --installed autogen gnutls guile guile@2 libxmlsec1 p11-kit $ brew uses libxml2 --installed autogen gettext gnutls libidn2 libxmlsec1 nghttp2 $ brew uses libxmlsec1 --installed $ brew uses openssl@1.1 --installed asdf autoconf automake berkeley-db gnutls libevent libxmlsec1 nghttp2 perl unbound $ brew uses readline --installed asdf autogen gettext gnutls guile guile@2 libidn2 libxml2 libxmlsec1 nghttp2 sqlite $ brew uses sqlite --installed $ brew uses xz --installed $ brew uses zlib --installed autogen binutils fnm gcc gettext gnutls libidn2 libxml2 libxmlsec1 nghttp2 sqlite zstd
こう見ると、依存されているものがあるのは libffi
libxml2
openssl@1.1
readline
zlib
でした。
また、 brew deps <package>
とすることで、指定パッケージが依存しているパッケージを調べることができます。
今のところ、Homebrewで使っているものとしては asdf、gcc、direnv、fnm といったあたりだったので、今度はそれらが依存しているパッケージを調べてみます。
$ brew deps asdf attr autoconf automake berkeley-db ca-certificates coreutils expat gdbm gmp libtool libyaml m4 ncurses openssl@1.1 perl readline unixodbc
$ brew deps gcc binutils gmp isl libmpc mpfr zlib zstd
$ brew deps direnv
$ brew deps fnm zlib
こうしてみると、 openssl@1.1
readline
zlib
あたりは他のものでも使っているようなので、それらはいったん残すことにして、それ以外のパッケージをアンインストールしてみることにします。
$ brew uninstall bzip2 libffi libxml2 libxmlsec1 sqlite xz Error: Refusing to uninstall /home/linuxbrew/.linuxbrew/Cellar/libffi/3.4.2 and /home/linuxbrew/.linuxbrew/Cellar/libxml2/2.9.12 because they are required by autogen, gettext, gnutls, guile, guile@2, libidn2, nghttp2 and p11-kit, which are currently installed. You can override this and force removal with: brew uninstall --ignore-dependencies bzip2 libffi libxml2 libxmlsec1 sqlite xz
libxml2
に依存しているパッケージがあるため、エラーになりました。
これを無視したい場合は --ignore-dependencies
を付ければ良いようなので、オプションを付けて再実行します。
$ brew uninstall --ignore-dependencies bzip2 libffi libxml2 libxmlsec1 sqlite xz
Python再インストールとMkDocsの動作確認
これでHomebrewの不要と思われる依存関係を取り除けたので、Pythonを再ビルドするためにアンインストール&再インストールをおこないます。
$ asdf uninstall python 3.10.2 $ asdf install python 3.10.2 python-build 3.10.2 /home/<user>/.asdf/installs/python/3.10.2 Downloading Python-3.10.2.tar.xz... -> https://www.python.org/ftp/python/3.10.2/Python-3.10.2.tar.xz Installing Python-3.10.2... python-build: use readline from homebrew python-build: use zlib from homebrew Installed Python-3.10.2 to /home/<user>/.asdf/installs/python/3.10.2
よく見ると、 python-build: use readline from homebrew
のようにHomebrewのパッケージを参照しているものが出力されていました。
もしかすると、当初Pythonをインストールしたときには除去した依存関係も出力されていたのかもしれません。
Pythonインストール後、venvで仮想環境を作ってからMkDocsのインストール&実行してみます。
$ python -m venv .venv $ . .venv/bin/activate (.venv) $ python -m pip install mkdocs (.venv) $ mkdocs new hoge INFO - Creating project directory: hoge INFO - Writing config file: hoge/mkdocs.yml INFO - Writing initial docs: hoge/docs/index.md (.venv) $ cd hoge (.venv) hoge$ mkdocs serve $ mkdocs serve INFO - Building documentation... INFO - Cleaning site directory INFO - Documentation built in 0.05 seconds INFO - [14:21:23] Serving on http://127.0.0.1:8000/
MkDocs、使えるようになりました。
定期メンテナンス
こうしてみると、依存関係でインストールされたものの、その後使われなくなるパッケージというのもけっこうありそうなので、そういったメンテナンスするのに以下の記事が参考になりそう。