3

J'ai un programme qui regroupe les statistiques d'annonces provenant de différents systèmes marketing. Tout fonctionne bien jusqu'à ce que je le convertisse au format .exe et l'exécute.Les requêtes python ne peuvent pas trouver de dossier avec un certificat lors de la conversion en .exe

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 

J'ai essayé de résoudre ce problème en utilisant ce code, mais le dossier MEI change constamment ses chiffres à chaque fois que je lance ce code il est donc inutile.

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) 

Je suis donc allé dans ce fichier

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

et essayé de commenter si des déclarations qui soulèvent cette erreur mais ont obtenu une erreur SSL. Je n'ai pas pu trouver un morceau de code responsable de la génération de ces chiffres MEI.

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)) 
+0

je devais mettre une déclaration de retour juste au début de la fonction cert_verify(). C'est très sale et horrible mais ça a marché. – Superbman

Répondre

2

J'ai également rencontré ce problème. Il semble que cela provient du regroupement de certificats cacert.pem qui n'est pas inclus dans le répertoire du package requests lorsque le programme est compilé. Le module requests utilise la fonction certifi.core.where pour déterminer l'emplacement de cacert.pem. Remplacer cette fonction et remplacer les variables définies par cette fonction semble résoudre le problème.

J'ajouté ce code au début de mon programme:

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