python请求在转换为.exe时找不到带有证书的文件夹 [英] python requests can't find a folder with a certificate when converted to .exe

查看:103
本文介绍了python请求在转换为.exe时找不到带有证书的文件夹的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序可以汇集来自不同营销系统的广告统计信息.一切正常,直到我将其转换为 .exe 格式并运行它.

I have a program that pools ad stats from different marketing systems. Everything works fine untill i convert it to the .exe format and run it.

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 1549, in __call__
    return self.func(*args)
  File "C:\Users\user\Desktop\alg\TSK_7. Marketing\report_gui.py", line 24, in <lambda>
    ok = tk.Button(root, text="DO NOT PRESS", bg="red", command=lambda: self.run())
  File "C:\Users\user\Desktop\alg\TSK_7. Marketing\report_gui.py", line 43, in run
    report.merge_all()
  File "C:\Users\user\Desktop\alg\TSK_7. Marketing\process_data.py", line 400, in merge_all
    fb_df     = self.fetch_fb()
  File "C:\Users\user\Desktop\alg\TSK_7. Marketing\process_data.py", line 156, in fetch_fb
    fb_campaigns = from_fb.run_fb(self.start_date, self.end_date)  # in JSON format
  File "C:\Users\user\Desktop\alg\TSK_7. Marketing\from_fb.py", line 110, in run_fb
    return s.get_stats()
  File "C:\Users\user\Desktop\alg\TSK_7. Marketing\from_fb.py", line 84, in get_stats
    params=params,
  File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\facebookads\adobjects\adaccount.py", line 1551, in get_insights
    return request.execute()
  File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\facebookads\api.py", line 653, in execute
    cursor.load_next_page()
  File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\facebookads\api.py", line 797, in load_next_page
    params=self.params,
  File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\facebookads\api.py", line 305, in call
    timeout=self._session.timeout
  File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\sessions.py", line 508, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\sessions.py", line 618, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\adapters.py", line 407, in send
    self.cert_verify(conn, request.url, verify, cert)
  File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\adapters.py", line 226, in cert_verify
    "invalid path: {0}".format(cert_loc))
OSError: Could not find a suitable TLS CA certificate bundle, invalid path: C:\Users\user\AppData\Local\Temp\_MEI253762\facebookads\fb_ca_chain_bundle.crt

我试图通过使用此代码来解决此问题,但每次运行此代码时,MEI 文件夹都会不断更改其数字,因此没有用.

I tried to fix that by using this code but MEI folder keeps changing its digits everytime i run this code so it's no use.

dst = r'C:\Users\user\AppData\Local\Temp\_MEI120642\facebookads'
file = 'fb_ca_chain_bundle.crt'

try:
    os.makedirs(dst);  ## it creates the destination folder
except:
    pass

shutil.move(file, dst)

所以我去了这个文件

C:\Users\user\AppData\Local\Programs\Python\Python35\Lib\site-packages\requests\adapters.py

C:\Users\user\AppData\Local\Programs\Python\Python35\Lib\site-packages\requests\adapters.py

并尝试评论引发此错误但出现 SSL 错误的语句.我找不到负责生成那些 MEI 数字的代码.

and tried to comment if statements that raise this error out but got an SSL error. I couldn't find a piece of code responsible for generating those MEI digits.

def cert_verify(self, conn, url, verify, cert):
    """Verify a SSL certificate. This method should not be called from user
    code, and is only exposed for use when subclassing the
    :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.

    :param conn: The urllib3 connection object associated with the cert.
    :param url: The requested URL.
    :param verify: Either a boolean, in which case it controls whether we verify
        the server's TLS certificate, or a string, in which case it must be a path
        to a CA bundle to use
    :param cert: The SSL certificate to verify.
    """
    if url.lower().startswith('https') and verify:

        cert_loc = None

        # Allow self-specified cert location.
        if verify is not True:
            cert_loc = verify

        if not cert_loc:
            cert_loc = DEFAULT_CA_BUNDLE_PATH

        if not cert_loc or not os.path.exists(cert_loc):
            raise IOError("Could not find a suitable TLS CA certificate bundle, "
                          "invalid path: {0}".format(cert_loc))

        conn.cert_reqs = 'CERT_REQUIRED'

        if not os.path.isdir(cert_loc):
            conn.ca_certs = cert_loc
        else:
            conn.ca_cert_dir = cert_loc
    else:
        conn.cert_reqs = 'CERT_NONE'
        conn.ca_certs = None
        conn.ca_cert_dir = None

    if cert:
        if not isinstance(cert, basestring):
            conn.cert_file = cert[0]
            conn.key_file = cert[1]
        else:
            conn.cert_file = cert
            conn.key_file = None
        if conn.cert_file and not os.path.exists(conn.cert_file):
            raise IOError("Could not find the TLS certificate file, "
                          "invalid path: {0}".format(conn.cert_file))
        if conn.key_file and not os.path.exists(conn.key_file):
            raise IOError("Could not find the TLS key file, "
                          "invalid path: {0}".format(conn.key_file))

推荐答案

我也遇到了这个问题.看起来它来自证书包 cacert.pem 在编译程序时未包含在 requests 包目录中.requests 模块使用函数 certifi.core.where 来确定 cacert.pem 的位置.覆盖此函数并覆盖此函数设置的变量似乎可以解决问题.

I ran into this problem as well. It looks like it comes from the certificate bundle cacert.pem not being included in the requests package directory when the program is compiled. The requests module uses the function certifi.core.where to determine the location of cacert.pem. Overriding this function and overriding the variables set by this function seems to fix the problem.

我将此代码添加到程序的开头:

I added this code to the beginning of my program:

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()

这篇关于python请求在转换为.exe时找不到带有证书的文件夹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆