Sphinxを最新版にアップデートしてmake html出来なくなった時の対処法

make出来なくなった

Sphinxを最新版(v1.0.7)にアップグレードしたところ、make htmlコマンドが以下のようなエラーを吐くようになりました。

$ make html
Running Sphinx v1.0.7
loading pickled environment... not yet created
AccessInit: hash collision: 3 for both 1 and 1

make htmlが手癖になりそうなくらい惚れ込んでたのでこれは困りました。

とりあえずググってみた

とりあえず何も考えずにエラー内容そのままでググると、検索結果の先頭にこれまたまんまなタイトルの記事が見つかりました。
AccessInit: hash collision: 3 for both 1 and 1

ここを読むと、どうやらPIL(画像処理ライブラリ)のインポート方法に問題があることがわかります。
例えばこの記事にあるように、Djangoが

# Djangoはこの方法で呼び出している
from PIL import Image

などと呼び出しているのに対し、pygmentsおよびdocutilsは

# pygmentsやdocutilsはこっち
import Image
import Image as PIL

などのように呼び出しています。

この2種類のPILのインポート方法はダブルスタンダード化していて、どっちで呼びだそうが呼ばれるものは同じPILなんです。が、Pythonインタプリタはこれら二つのImageモジュールが別物だと認識してしまうとのことです。なので名前衝突が起こってしまうというわけですね。

尚、最新のpygmentsはすでに「from PIL import 〜」方式に修正されています。docutilsは未だに「import Image」ですが。

Sphinxはというと

Sphinxの公式アナウンスでこんなのがありました。

Release 1.0.7 (Jan 15, 2011)
#599: Import PIL as from PIL import Image.
http://sphinx.pocoo.org/changes.html

「Import PILをfrom PIL import Imageに変更したよー」ってことですね。そうです。この修正によって「PILの二重呼び出し」現象が再現されてしまったわけです。

というわけでdocutilsを修正してみる

AccessInit: hash collision: 3 for both 1 and 1の最後で紹介されているdocutils patchに書かれている通りに、docutilsフォルダ(Python2x/Lib/site-packages/docutils)以下の3つのファイルを修正します。

まずはimages.py

場所はPython2x/Lib/site-packages/docutils/parsers/rst/directives/images.py

from docutils.parsers.rst.roles import set_classes
 
try:
    import Image as PIL                        # PIL
except ImportError:
    PIL = None

これを以下のように修正

from docutils.parsers.rst.roles import set_classes
 
try:
    import PIL
except ImportError:
    try:
        import Image as PIL                        # PIL
    except ImportError:
        PIL = None

続いてhtml4css1/__init__/py

場所はPython2x/Lib/site-packages/docutils/writers/html4css1/__init__.py

import time
import re
try:
    import Image                        # check for the Python Imaging Library
except ImportError:
    Image = None

これまた以下のように

import time
import re
try:
    from PIL import Image                        # check for the Python Imaging Library
except ImportError:
    try:
        import Image
    except ImportError:
        Image = None

最後にodf_odt/__init__.py

場所はPython2x/Lib/site-packages/docutils/writers/odf_odt/__init__.py

#
# Is the PIL imaging library installed?
try:
    import Image
except ImportError, exp:
    Image = None

これも(ry

#
# Is the PIL imaging library installed?
try:
    from PIL import Image
except ImportError:
    try:
        import Image
    except ImportError:
        Image = None

以上で修正は終わりです。

make html してみる

やったーちゃんと動いたー!

内容が内容なだけに他にも困ってる人がいるかもと思って記事に起こしてみたのでした。参考になれば幸いです。また、「それやっちゃまずいよ」とかあれば教えていただけると嬉しいです。

それと、終わったあとにこんな記事を見つけました↓

ノート

Python 環境 (easy_install) に Sphinx をインストールしてはいけません。 buildout で作成したバージョンと衝突する可能性があるので削除してください。他のプロジェクトで Sphinx が必要な場合は virtualenv を使用してください。

Plone 開発者マニュアルを Plone CMS にアップロードする方法 — Plone 開発者マニュアル v1.0 documentation

うんうん、Python環境は出来るだけ汚さないように積極的にvirtualenvを活用すべきってのは僕も賛成です。