前言
PyInstaller 是一个强大而使用简单的 Python 代码打包程序,使用它,我们可以快速将代码打包成可执行程序。但是,如果代码中包含requests
库,则打包后的程序会出现OSError: Could not find a suitable TLS CA certificate bundle, invalid path:
。这一问题出现的原因是在打包时,requests库释放在用户临时文件夹内的CA证书没有被一起打包,所以解决的思路就是将证书手动加入代码内。
cacert.pem
文件可以从https://curl.se/docs/caextract.html下载到
解决方案1
来自StackOverflow一搜就能找到的方法是将CA证书的路径临时地写入系统环境变量中
import sys, os
def override_where():
""" overrides certifi.core.where to return actual location of cacert.pem"""
# change this to match the location of cacert.pem
return os.path.abspath("cacert.pem")
# is the program compiled?
if hasattr(sys, "frozen"):
import certifi.core
os.environ["REQUESTS_CA_BUNDLE"] = override_where()
certifi.core.where = override_where
# delay importing until after where() has been replaced
import requests.utils
import requests.adapters
# replace these variables in case these modules were
# imported before we replaced certifi.core.where
requests.utils.DEFAULT_CA_BUNDLE_PATH = override_where()
requests.adapters.DEFAULT_CA_BUNDLE_PATH = override_where()
加入如下代码后,将cacert.pem
置于打包完成后的exe文件同目录即可使exe可执行程序正常运行了
解决方法2
上述方法,能够解决标题中的问题,但是我们将不得不将一个pem证书和可执行文件捆绑在一起。所以,一个有点奇怪的方式是将证书内容保存为一个Python变量值,在主程序内将该值写入到一个临时文件中,再将该临时文件加入系统环境变量中,这样便可解决方法1所带来的问题。
在cert.py
中,我们写入证书内容
CERT_DATA = """
证书内容
"""
在主程序main.py
中
import tempfile
import os, sys
from cert import CERT_DATA
temp_cert = tempfile.NamedTemporaryFile(delete=False, encoding="utf-8", mode="w")
temp_cert.write(CERT_DATA)
temp_cert.flush()
os.environ['REQUESTS_CA_BUNDLE'] = temp_cert.name
再次执行Pyinstaller -F main.py
,新的可执行文件便可以顺利运行了
转载请标注来源