ちら帳

喉元を過ぎると熱さを忘れる自分の為の、ちら裏メモ帳ブログです。

pipをグローバルで使っていた環境でyumで入れたパッケージがおかしくなった話

※過去に自分が他の媒体で書いていた記事を移動してきたものなので、情報が古い可能性があります。ご注意ください。

yumとpipの競合

pipのインストール状況によりますが、yum経由でインストールしたPythonパッケージも、pipでグローバルにインストールしたパッケージも同じディレクトリにインストールされてしまうことがあります(例:/usr/lib/python2.7/site-packages/)

このような状態でグローバルでpipを使用すると、yum経由でインストールしたPythonパッケージを上書きできてしまいます。

競合によって発生する問題

yumでインストールしたパッケージがエラーで利用できなくなることがあります。

また、yumからはpipがPythonパッケージを更新したことを検知できないため、yumによるパッケージの管理で一部の依存関係が自動で解決できなくなります。

実際に起きたpipによるPythonパッケージの上書きが原因となった問題

SSL証明書の更新で利用しているcertbotがある日、モジュールの不整合を起こすようになりました。

ImportError: 'pyOpenSSL' module missing required functionality. Try upgrading to v0.14 or newer. · Issue #5534 · certbot/certbot · GitHub

一見、pyOpenSSLのバージョン不整合が問題のようですが、実際はyumのrequests, urllib3, sixのPythonパッケージをpipで上書きしてしまったのが原因でした。

問題となっているパッケージをpipでアンインストールして、yumで再インストールしたところ、エラーが発生しなくなりました。

sudo pip uninstall requests
sudo pip uninstall urllib3
sudo pip uninstall six

sudo yum reinstall python-requests
sudo yum install python-urllib3
sudo yum install python-six

競合を起こさないようにするには

システムにpipをインストールせず、仮想環境内でのみpipを扱うようにします。

少なくともCentOSは7でもシステムの使っているPythonが2.7.5なのでpipが付属していません(執筆当時の情報なので変わる可能性があります) そのため、python2-pipなどをインストールしなければ、誤ってシステムで使ってしまうことはありません。

yumpython-virtualenvをインストールします。

sudo yum install python-virtualenv

仮想環境を作り、その中でpipを使うようにします。

virtualenv myenv
source myvenv/bin/active

virtualenv内で使えるpipはおそらくバージョンが古いため、開発等をおこなう前にアップデートをおこないます。pipが使用するsetuptoolsのパッケージもアップデートします。

pip install -U pip
pip install -U setuptools

すでに競合が起きている場合

競合の見つけ方

rpm -qV {パッケージ名} でパッケージのファイルの検証ができます。 元のパッケージから変更されている箇所があれば、そのファイルの変更状態が出力されます。変更が無ければ何も出力されません。

$ rpm -qV httpd
S.5....T.  c /etc/httpd/conf.d/autoindex.conf
S.5....T.  c /etc/httpd/conf/httpd.conf
  /run/httpd/htcacheclean が見つかりません。 (許可がありません)
..?......    /usr/sbin/suexec
  /var/cache/httpd/proxy が見つかりません。 (許可がありません)

yumで管理しているpythonのパッケージ名が大体わかっているのであれば、検証用のシェルを書いて一気に処理を回してしまっても良いかもしれません。

#!/bin/sh

for package in `rpm -qa | egrep "python|pytz|yum"`
do
    echo $package
    rpm -qV $package
done

あるいはpipでパッケージをインストールした時のログが残っているのであれば、内容からpipが上書きした可能性のあるパッケージにあたりをつけることができます。

# ログ中にこの記述がある場合、yumのパッケージをpipで上書きしている可能性があります
Found existing installation: urllib3 1.10.2
    Uninstalling urllib3-1.10.2:
      Successfully uninstalled urllib3-1.10.2

競合の直し方

pipでアンインストールして、使っているパッケージ管理ソフトで再インストールします。

pipはyumのように履歴からロールバックができないので、現在のパッケージのインストール状況を復元できるようにバックアップを取っておきます。

pip freeze > packages_requirements.txt

pipでパッケージをアンインストールします。 依存パッケージは自動でアンインストールされないので、必要があれば依存するパッケージも手動でアンインストールします。

sudo pip uninstall urllib3

yumでパッケージを再インストールします。 yum reinstallでエラーが起こる場合はコマンドをyum installに変更してください。

sudo yum reinstall python-urllib3

pipのアンインストール

yumからpipをインストールした場合は、yumでアンインストールします。 pipに依存するパッケージも一緒に削除されるので、依存関係をよく確認してからremoveを実行してください。

sudo yum remove pip

get-pip.pyを実行してpipをインストールした場合は、pipコマンドでpipをアンインストールします。 インストール時にpipとwheelがまとめてインストールされているはずなので、wheelも一緒にアンインストールします。

sudo pip uninstall wheel
sudo pip uninstall pip

Pythonのバージョンによっては、標準でpipが付属していますが、その場合はアンインストールはしないようにしてください。

参考ページ

Tadej Janež – Don't mix yum/dnf and pip for installation of system-wide Python packages

[Fix] ImportError: 'pyOpenSSL' module missing required functionality. Try upgrading to v0.14 or newer. - GetPageSpeed