pip
Python3

pipが動作しないエラーの解決


環境


  • Mac OS X 10.11.6 (El Capitan)

  • Python 3.5.1

  • pip 9.0.1

  • 今日の日付 2018-07-18 (案外重要)


経緯

twitterのbotが作りたくて、tweepyかtwythonをpipでインストールしようとしました。

$ pip install tweepy

すると、以下のエラーが発生

Collecting tweepy

Could not fetch URL https://pypi.python.org/simple/tweepy/: There was a problem confirming the ssl certificate: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:645) - skipping
Could not find a version that satisfies the requirement tweepy (from versions: )
No matching distribution found for tweepy


解決策(?)その1

検索してみると、下記のコマンドを使ってpipをアップグレードするといい、という情報が見つかりました。

curl https://bootstrap.pypa.io/get-pip.py | python3

参考:

https://github.com/pypa/pip/issues/5236

その通りやってみると…

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

Dload Upload Total Spent Left Speed
100 1603k 100 1603k 0 0 2151k 0 --:--:-- --:--:-- --:--:-- 2149k
Collecting pip
Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError('certificate verify failed, error code: 5',),)': /simple/pip/
Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError('certificate verify failed, error code: 5',),)': /simple/pip/
Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError('certificate verify failed, error code: 5',),)': /simple/pip/
Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError('certificate verify failed, error code: 5',),)': /simple/pip/
Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError('certificate verify failed, error code: 5',),)': /simple/pip/
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError(SSLError('certificate verify failed, error code: 5',),)) - skipping
Could not find a version that satisfies the requirement pip (from versions: )
No matching distribution found for pip
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError(SSLError('certificate verify failed, error code: 5',),)) - skipping

うまくいきません。


原因

エラーの中心はcertificate verify failedですね。「証明書の検証に失敗」です。

調べてみると、どうやら、パッケージをインストールする先方のURLが変更になり、pip側が「そんなURLは知らないぞ!信用出来ないんじゃないのか??」と疑って、エラーを出している、ということっぽいです。多分。ちゃんとわかってなくてすみません。

参考:

https://github.com/pypa/pip/issues/5288

https://packaging.python.org/guides/migrating-to-pypi-org/

↑2個目のURLが公式アナウンスです。


解決策(?)その2

次の参考URLに書いてあるように、新しいURLについて「このURLは信用していいよ〜」という情報をpipに教えてあげましょう。

参考:

https://stackoverflow.com/questions/25981703/pip-install-fails-with-connection-error-ssl-certificate-verify-failed-certi

pypi.orgfiles.pythonhosted.orgを信用するように指示すれば良いようです。

でも、この方法ではうまくいきませんでした。



pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org <package_name>

そもそもpipをアップグレードする必要があるので、先に使いたいコマンドはcurlなんですよね。pipではなく。

しかし

curl https://bootstrap.pypa.io/get-pip.py | python3

の中でどうやらpipが使われてるらしく、ここでは--trusted-hostの指定をしていないので、結局同じエラーがでる。

ということで、同じ参考URLにあったもう一つの方法を使います。

pip.confという設定ファイルを作って、そこに「このURLは信用していいよ」という内容を記述します。(Windowsの場合はpip.ini)


結論

結局、下記のようにしてうまくいきました。


pip.confの作成(Windowsの場合はpip.ini)

まず、pip.confを所定の場所に作り、下記の記述をします。


~/.pip/pip.conf

[global]

trusted-host = pypi.python.org
pypi.org
files.pythonhosted.org

これで、これらのURLは信用され、これらのURLからパッケージをダウンロードしてくれるようになります。

pip.confを置く場所については下記を参考に。

参考:

https://stackoverflow.com/questions/45337029/pip-conf-not-paying-attention-to-trusted-host


pipのアップグレード

curl https://bootstrap.pypa.io/get-pip.py | python3

これを実行します。pip10.0.1にアップグレードされます。


パッケージのインストール

ようやくここまで来ましたが、これが当初やりたかったやつです。本来、これだけでできるはずなんだよなあ。

僕の場合はtweepyをインストールしました。

pip install tweepy

以上です。


追記(2018-07-19)VPSサーバーでもpipを動かす


VPSサーバーの環境


  • CentOS Linux release 7.0.1406 (Core)

  • curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.15.4 zlib/1.2.7 libidn/1.28 libssh2/1.4.3

  • Python 3.6.2

  • pip 9.0.1


経緯

僕の場合tweepyはVPSサーバー上で動いてくれないと意味がないので、VPSサーバーにも上記の方法でインストールしようとした所、

curl https://bootstrap.pypa.io/get-pip.py | python3.6

を実行した時点で、ローカルの時とは異なるエラーが発生。

(コマンドの最後がpython3ではなくpython3.6になっているのは、僕のVPS環境でpython3を呼び出すコマンドがpython3.6になっているからです。)

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
curl: (35) Peer reports incompatible or unsupported protocol version.

調べてみると、どうも、Curlのバージョンが古いのが原因のようです。

参考:

https://stackoverflow.com/questions/43975973/how-to-fix-error-failed-to-download-on-rbenv-install

--verboseオプションをつけて

curl --verbose https://bootstrap.pypa.io/get-pip.py | python3.6

を実行してみると、以下のような詳細が出ました。

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* About to connect() to bootstrap.pypa.io port 443 (#0)
* Trying 2a04:4e42:11::175...
* Connected to bootstrap.pypa.io (2a04:4e42:11::175) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* NSS error -12190 (SSL_ERROR_PROTOCOL_VERSION_ALERT)
* Peer reports incompatible or unsupported protocol version.
* Error in TLS handshake, trying SSLv3...
> GET /get-pip.py HTTP/1.1
> User-Agent: curl/7.29.0
> Host: bootstrap.pypa.io
> Accept: */*
>
* Connection died, retrying a fresh connect
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
* Closing connection 0
* Issue another request to this URL: 'https://bootstrap.pypa.io/get-pip.py'
* About to connect() to bootstrap.pypa.io port 443 (#1)
* Trying 2a04:4e42:11::175...
* Connected to bootstrap.pypa.io (2a04:4e42:11::175) port 443 (#1)
* TLS disabled due to previous handshake failure
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* NSS error -12286 (SSL_ERROR_NO_CYPHER_OVERLAP)
* Cannot communicate securely with peer: no common encryption algorithm(s).
* Closing connection 1
curl: (35) Peer reports incompatible or unsupported protocol version.

TLSのハンドシェイクプロトコルでエラーが発生し、NSS error として報告されています。

(ハンドシェイクプロトコルでは、やりとりする2者が両方とも使える暗号化プロトコルを選ぶのですが、そこで合致するプロトコルがなかったということらしい。)

ということで、参考URLにある方法をそのまま使って、NSS error を解決します。


解決策(?)1


NSSのアップデート

ルート権限で以下を実行します。

yum update nss nss-util nspr

……結果から言うと、何も解決しませんでした。なんなんだ。


解決策(?)2

参考:

https://support.plesk.com/hc/en-us/articles/214029229-How-to-update-cURL-to-the-latest-version-on-a-Plesk-server

こちらのサイトにある方法を試します。

yum update curl.x86_64

を実行した後に、curlのバージョンを確認。

curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.34 zlib/1.2.7 libidn/1.28 libssh2/1.4.3

はい。変わってませんね。7.29のままです。

NSSのバージョンが3.15.4から3.34に上がってますが、NSSをupdateしたからなのか、今curlのupdateをしたからなのか、今となってはわからなくなってしまった。

どっちにしても、問題は解決していない。


解決策(?)3

下記3サイトに、ほぼ同じ方法が解決策が書いてあるので、実行してみます。

参考:

https://support.plesk.com/hc/en-us/articles/214029229-How-to-update-cURL-to-the-latest-version-on-a-Plesk-server

https://serverfault.com/questions/321321/upgrade-curl-to-latest-on-centos

https://stackoverflow.com/questions/28495444/how-to-upgrade-php-curl-to-version-7-36-0

/etc/yum.repos.d/city-fan.repoというファイルを作り、中身を次のようにします。


/etc/yum.repos.d/city-fan.repo

[CityFan]

name=City Fan Repo
baseurl=http://www.city-fan.org/ftp/contrib/yum-repo/rhel$releasever/$basearch/
enabled=1
gpgcheck=0

そしたら次を実行します。

yum clean all

yum install curl

すると………

次のエラーが出ます!!!!

Loaded plugins: fastestmirror

CityFan | 2.9 kB 00:00:00
base | 3.6 kB 00:00:00
epel/x86_64/metalink | 6.6 kB 00:00:00
epel | 3.2 kB 00:00:00
extras | 3.4 kB 00:00:00
Could not retrieve mirrorlist https://mirrors.iuscommunity.org/mirrorlist?repo=ius-centos7&arch=x86_64&protocol=http error was
14: curl#60 - "Peer's Certificate issuer is not recognized."

One of the configured repositories failed (Unknown),
and yum doesn't have enough cached data to continue. At this point the only
safe thing yum can do is fail. There are a few ways to work "fix" this:

1. Contact the upstream for the repository and get them to fix the problem.

2. Reconfigure the baseurl/etc. for the repository, to point to a working
upstream. This is most often useful if you are using a newer
distribution release than is supported by the repository (and the
packages for the previous distribution release still work).

3. Disable the repository, so yum won't use it by default. Yum will then
just ignore the repository until you permanently enable it again or use
--enablerepo for temporary usage:

yum-config-manager --disable <repoid>

4. Configure the failing repository to be skipped, if it is unavailable.
Note that yum will try to contact the repo. when it runs most commands,
so will have to try and fail each time (and thus. yum will be be much
slower). If it is a very temporary problem though, this is often a nice
compromise:

yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true

Cannot find a valid baseurl for repo: ius/x86_64

はい。

何にもうまくいかないな……。。。。。


結論(curlのアップデートを諦める)

curlのアップデートを諦めます。

要は、pythonプログラムである https://bootstrap.pypa.io/get-pip.py を実行すればいいわけなので、これを直接ローカルにダウンロードして、scpでサーバーにアップロードします。

で、普通にpythonプログラムとして実行

python3.6 get-pip.py

これでVPSサーバー上でもpipを10.0.1に更新できました。

そのままpip install tweepyも問題なく済みました。

curlのアップデートがうまくいかなかった理由がわかる方がいらっしゃいましたら、どうか教えてください。