Python 获取 NCBI 基因名 SSL 证书出现异常?

源自于前几天对一批转录本的批量化操作的一些记录。

即想要通过 Python 在线获取某个转录本对应的基因 Symbol 时,发现出现 SSL 无法获取本地证书:unable to get local issuer certificate (_ssl.c:1056)!

python 复制代码
>>> from Bio import SeqIO
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]"
>>> records = SeqIO.parse(Entrez.efetch(id='NM_001009537.4', db="nucleotide", rettype="gb", retmode="text"), "gb")
Traceback (most recent call last):
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/urllib/request.py", line 1317, in do_open
    encode_chunked=req.has_header('Transfer-encoding'))
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/http/client.py", line 1229, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/http/client.py", line 1275, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/http/client.py", line 1224, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/http/client.py", line 1016, in _send_output
    self.send(msg)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/http/client.py", line 956, in send
    self.connect()
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/http/client.py", line 1392, in connect
    server_hostname=server_hostname)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/ssl.py", line 412, in wrap_socket
    session=session
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/ssl.py", line 853, in _create
    self.do_handshake()
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/ssl.py", line 1117, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/site-packages/Bio/Entrez/__init__.py", line 184, in efetch
    return _open(cgi, variables, post=post)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/site-packages/Bio/Entrez/__init__.py", line 543, in _open
    handle = _urlopen(cgi)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/urllib/request.py", line 525, in open
    response = self._open(req, data)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/urllib/request.py", line 543, in _open
    '_open', req)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/urllib/request.py", line 503, in _call_chain
    result = func(*args)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/urllib/request.py", line 1360, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/urllib/request.py", line 1319, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)>

根据网络上的解析,当使用 urllib.urlopen 打开一个 https 链接时,会验证一次 SSL 证书。而当目标网站使用的是自签名的证书时就会抛出如下异常:

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)

解决方法也很简单,下面是个人简单总结的 3 种常用解决方法。

方法一,全局取消证书验证

python 复制代码
>>> import ssl
>>> ssl._create_default_https_context = ssl._create_unverified_context

方法二,指定位置安装证书

  1. 查看证书默认位置。
python 复制代码
>>> import ssl
>>> print(ssl.get_default_verify_paths())
DefaultVerifyPaths(cafile=None, capath='/Bioinfo/Pipeline/SoftWare/LibDependence/openssl-1.1.1/ssl/certs', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/Bioinfo/Pipeline/SoftWare/LibDependence/openssl-1.1.1/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/Bioinfo/Pipeline/SoftWare/LibDependence/openssl-1.1.1/ssl/certs')

由于在 openssl_cafile 中指定的 ca 文件(cert.pem)不存在,所以导致上面的错误。

  1. 下载 ca 文件,将下载的 ca 文件放到 openssl_cafile 指定位置。注意,如果放到 openssl_capath 目录下还会出现类似的问题,一定要放到 openssl_cafile 指定的位置。
python 复制代码
$ cd /Bioinfo/Pipeline/SoftWare/LibDependence/openssl-1.1.1/ssl
$ wget http://curl.haxx.se/ca/cacert.pem -O cert.pem --no-check-certificate

方法三,设置环境变量

也可以参考 stackoverflow 上的做法,通过修改下面环境变量的方式解决(亲测可行)

python 复制代码
export SSL_CERT_FILE=/usr/local/etc/openssl/cert.pem
export REQUESTS_CA_BUNDLE=/usr/local/etc/openssl/cert.pem

最后,问题解决。

python 复制代码
>>> from Bio import SeqIO
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]"
>>> records = SeqIO.parse(Entrez.efetch(id='NM_001009537.4', db="nucleotide", rettype="gb", retmode="text"), "gb")
>>> for record in records:
...     for feature in record.features:
...         if feature.type == "gene":
...             print(feature.qualifiers['gene'])
...
['Zfp799']
相关推荐
沃洛德.辛肯9 分钟前
PyTorch 的 F.scaled_dot_product_attention 返回Nan
人工智能·pytorch·python
noravinsc21 分钟前
人大金仓数据库 与django结合
数据库·python·django
豌豆花下猫28 分钟前
Python 潮流周刊#102:微软裁员 Faster CPython 团队(摘要)
后端·python·ai
yzx9910131 小时前
Gensim 是一个专为 Python 设计的开源库
开发语言·python·开源
麻雀无能为力1 小时前
python自学笔记2 数据类型
开发语言·笔记·python
Ndmzi1 小时前
matlab与python问题解析
python·matlab
懒大王爱吃狼1 小时前
怎么使用python进行PostgreSQL 数据库连接?
数据库·python·postgresql
猫猫村晨总1 小时前
网络爬虫学习之httpx的使用
爬虫·python·httpx
web150854159352 小时前
Python线性回归:从理论到实践的完整指南
python·机器学习·线性回归
ayiya_Oese2 小时前
[训练和优化] 3. 模型优化
人工智能·python·深度学习·神经网络·机器学习