エラーメッセージ
<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
別の表記
- urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
山括弧の中のテキストは元になった ssl のエラーで、状況によって異なります(「self-signed certificate in certificate chain」「certificate has expired」など)。Python はソースの位置と「>」でこれを閉じます。例:「(_ssl.c:1082)>」。
Python urllib.request — urllib.error.URLError wrapping ssl.SSLCertVerificationError
このエラーの意味
urllib.request.urlopen() はあらゆる接続の問題を URLError でラップするため、TLS の失敗は「<urlopen error …>」の中に現れます。www.python.org を含むすべての公開サイトでこのエラーが起きる場合、その Python プロセスには使用できる CA 証明書がまったくありません。典型的なのは macOS の python.org 版インストーラーで、同梱の OpenSSL は「Install Certificates.command」を実行するまでキーチェーンを読み込みません。
発生する理由
証明書が入っていない macOS の python.org 版 Python
よくあるインストーラーは、空のトラストストアを持つ OpenSSL と、certifi をインストールしてリンクするヘルパースクリプト「Install Certificates.command」を同梱しています。このスクリプトを実行しない(または後から新しいマイナーバージョンをインストールする)と、urlopen は何も検証できなくなります。
CA バンドルのない最小構成のイメージやカスタムビルドの Python
ときどきソースからコンパイルした Python や、scratch イメージ、distroless イメージにコピーした Python は、OpenSSL のデフォルトのバンドルのパスを探しますが、そのイメージにはそのパスが存在しません。
TLS を検査するプロキシ
ときどき一部のサイトだけで失敗する場合や、社内ネットワークで失敗が始まった場合は、この Python が信頼していないプロキシのルートが原因である可能性が高いです。
SSL_CERT_FILE または SSL_CERT_DIR が誤った場所を指している
まれこれらの変数は、プロセス全体でデフォルトの場所を置き換えます。空のファイルや無関係なファイルを指定すると、すべての検証が失敗します。
修正方法
- 1.
macOS:Install Certificates.command を実行する
python.org の Python のバージョンごとに、Finder またはターミナルからこのスクリプトを実行し、その後でデフォルトの CA ファイルのパスが存在することを確認してください。
bash # macOS, python.org installer (one script per installed version) "/Applications/Python 3.14/Install Certificates.command" python3 -c "import ssl; print(ssl.get_default_verify_paths().openssl_cafile)" - 2.
certifi から作成したコンテキストを渡す
どこでも動作しなければならないスクリプトでは、certifi.where() から明示的に SSL コンテキストを作成してください。ルートが最新の状態に保たれるよう、certifi を更新し続けてください。
python # Explicit, portable: use certifi's Mozilla bundle for this request # pip install certifi import certifi, ssl, urllib.request ctx = ssl.create_default_context(cafile=certifi.where()) urllib.request.urlopen("https://www.python.org/", context=ctx) - 3.
または OS のトラストストアを使う
truststore.inject_into_ssl() を呼び出すと、urllib、http.client、ssl を基盤とするライブラリが OS を通じて検証するようになり、IT 部門が配布した会社のルートも使われます。
python # Or verify with the operating system's store (macOS Keychain, Windows, Linux bundle) # pip install truststore==0.10.5 import truststore truststore.inject_into_ssl() - 4.
環境変数による上書きを確認する
SSL_CERT_FILE と SSL_CERT_DIR が必要なルートを含まないファイルを指している場合は、これらの設定を解除してください。
bash env | grep -E '^SSL_CERT_(FILE|DIR)=' python3 -c "import ssl; print(ssl.get_default_verify_paths())"