2014-01-18 4 views
4

Я написал простую программу, которая открывает файл csv и текст всех номеров в нем. Я использую Twilio (twilio-python) в качестве поставщика услуг. Мой код отлично работает как скрипт python. Однако, когда я скомпилирую скрипт (используя py2exe), ошибки exe-файла. Это ошибка, я получаю из файла журнала ....Ошибки модуля Twilio Python после компиляции

Traceback (most recent call last): 
File "sms.py", line 39, in <module> 
File "twilio\rest\resources\messages.pyc", line 112, in create 
File "twilio\rest\resources\base.pyc", line 352, in create_instance 
File "twilio\rest\resources\base.pyc", line 204, in request 
File "twilio\rest\resources\base.pyc", line 129, in make_twilio_request 
File "twilio\rest\resources\base.pyc", line 101, in make_request 
File "httplib2\__init__.pyc", line 1570, in request 
File "httplib2\__init__.pyc", line 1317, in _request 
File "httplib2\__init__.pyc", line 1252, in _conn_request 
File "httplib2\__init__.pyc", line 1021, in connect 
File "httplib2\__init__.pyc", line 80, in _ssl_wrap_socket 
File "ssl.pyc", line 387, in wrap_socket 
File "ssl.pyc", line 141, in __init__ 
ssl.SSLError: [Errno 185090050] _ssl.c:340: error:0B084002:x509 certificate    
routines:X509_load_cert_crl_file:system lib 

Я не Получать эту ошибку, когда я использую неразделанный скомпилированный код (ниже)

import sys #2 params --- /path/to/contact/file --- up to 160 char msg 
    import csv 
    import time 

    from twilio.rest import TwilioRestClient 
    ACCOUNT_SID = "**************************" 
    AUTH_TOKEN = "**************************" 
    client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN) 

    sys.argv.pop(0) 
    contactFile = sys.argv[0] 
    sys.argv.pop(0) 
    msg = (' ').join(sys.argv) 

    print contactFile 
    print " " 
    print msg 

    info = [] 
    with open(contactFile,'rb') as csvfile: 
    reader = csv.reader(csvfile, delimiter=',', quotechar='|') 
     for row in reader: 
     info.append(row) 

    contactCount = len(info)-1 

    if contactCount > 0: 
    #remove first item from list because its not a value that is needed.... 
    info.pop(0) 

    for i in info: 
     print " " 
     contactName = i[0] 
     phoneNumber = i[1] 
     print "Texting " + contactName + "... \n" 
     client.messages.create(
     to=phoneNumber, 
     from_="+14782856136", 
     body=msg 
     ) 
     time.sleep(1.5) 
    else: 
    print("SMSify Error \n The contact file doesn't have any contacts in it.") 

Любые мысли о что происходит??

EDIT:

Вот мой setup.py файл

from distutils.core import setup 
import py2exe, sys, os 
sys.argv.append('py2exe') 
Mydata_files = [('cacert.pem', ['C:\\Python27\\Lib\\site-  
packages\\twilio\\conf\\cacert.pem'])] 

setup(
    console=['sms.py'], 
    data_files = Mydata_files, 
    options={ 
       "py2exe":{ 
        "bundle_files": 1, 
        "compressed": True 
       } 
     } 
) 
+0

Простым решением было бы - вы можете физически разместить сертификаты в своем дистрибутивом и явно передать место сертификации в коде. см. http://stackoverflow.com/a/34227183/318700 – HVS

ответ

14

Это произошло потому, что self-signed certificate файл пропустил в связке.

Эта проблема для requests и модулей.

Например, если у вас есть файл с именем req_example.py, что с помощью request модуля:

import requests 
url = 'https://google.com/' 
requests.get(url) 

Это работает, когда вы запускаете его как python req_example.py, но когда расслоение, он не работает.

Или если у вас есть файл с именем http2_example.py, что с помощью http2 модуля:

import httplib2 
url = 'https://google.com/' 
http = httplib2.Http() 
http.request(url) 

Это работает, когда вы запускаете его как python http2_example.py, но когда расслоение, он не работает.

Чтобы исправить это, у вас есть два варианта: один bad и один good.

  1. Отключить проверку SSL сертификаты:

    Чтобы сделать это для requests модуля:

    import requests 
    url = 'https://google.com/' 
    requests.get(url, verify=False) 
    

    И для модуля:

    import httplib2 
    http = httplib2.Http(disable_ssl_certificate_validation=True) 
    http.request(url) 
    
  2. Добавить self-signed certificate файл Bundle:

    Для requests модуля, файл cacert.pem находится в:

    .../PythonXX/lib/site-packages/requests/cacert.pem

    И модуль находится в:

    .../PythonXX/lib/site-packages/httplib2/cacerts.txt

    Для каждого из них, вы можете скопировать его в вашего проекта (или просто адрес к нему),

    И configдля его включения:

    setup(console=['temp.py'], 
        # for `requests` module 
        data_files=['cacert.pem']) # or data_files=['cacerts.txt']) for `httplib2` 
    

    и изменить свой код, чтобы использовать это для request модуля:

    import os 
    import requests 
    url = 'https://google.com/' 
    cert ='cacert.pem' 
    # or os.environ['REQUESTS_CA_BUNDLE'] = cert 
    os.environ['REQUESTS_CA_BUNDLE'] = os.path.join(os.getcwd(), cert) 
    requests.get(url) 
    

    И для модуля:

    import httplib2 
    cert = 'cacerts.txt' 
    http = httplib2.Http(ca_certs=cert) 
    http.request(url) 
    

    Или, если ваша версия является 0.8 , вы можете создать файл, который should по имени ca_certs_locater.py и определите функцию get, , которая возвращает путь к файлу ca_certs.

    def get(): 
        return 'cacerts.txt' 
    

Хорошо, теперь для вашей ошибки, и для twilio модуля, он use и cacert.pem его в:

.../twilio/conf/cacert.pem

Так что вам нужно добавить этот файл setup.py, как описано выше.

Но twilio сам выполняет функции с именем get_cert_file, которые передают ca_cert файл на номер .

Я думаю, что если вы используете ca_certs_locater.py, что описанный выше, он также будет работы для того, , но если нет, то есть еще в ugly вариант, так что вы можете обезьяна патч get_cert_file функция twilio:

from twilio.rest.resources.base import get_cert_file 
get_cert_file = lambda: 'cacert.pem' 

Обратите внимание, что это может быть проблемой для twilio или даже для py2exe или PyInstaller.

+0

Хорошо. Поэтому я добавил файл twilio cacert.pem в файл setup.py. Мой файл setup.py размещен выше. Я все равно получаю ту же ошибку. –

+0

Это не работает, потому что 'twilio' хочет загрузить его из самого пути, то есть' .../twilio/conf/cacert.pem', но этого не существует в пакете (внутри 'library.zip' файла) , попробуйте 'ca_certs_locater.py', и если не работайте, попробуйте' patch'. –

+0

Хорошо. Поэтому я создаю файл ca_certs_locater.py и добавляю функцию get. Теперь, я должен рассказать об этом в setup.py? Ответ немного расплывчатый. Спасибо за вашу помощь! –

1

Возможно, для py2exe может возникнуть путь для объединения не-Python-файлов, таких как шаблоны или в этом случае сертификат SSL, хранящийся в cacert.pem. Обычно это делается автоматически с помощью MANIFEST.in, но я не уверен, как этот проект справляется с этим. Проверьте документацию для получения дополнительной информации.

2

У меня была такая же проблема с Twilio и pyinstaller, и был в состоянии исправить это путем изменения модуля base.py в Twilio \ \ остальных ресурсов:

def get_cert_file(): 
""" Get the cert file location or bail """ 
# XXX - this currently fails test coverage because we don't actually go 
# over the network anywhere. Might be good to have a test that stands up a 
# local server and authenticates against it. 
    try: 
    # Apparently __file__ is not available in all places so wrapping this 
    # in a try/catch 
    current_path = os.path.realpath(__file__) 
    #ca_cert_path = os.path.join(current_path, "..", "..", "..", (old path) 
    #       "conf", "cacert.pem") 
    ca_cert_path = os.getcwd() + '\Config\cacert.pem' (my new path) 

    return os.path.abspath(ca_cert_path) 

(я храню мой файл cacert.pem в папке Config из моего основного каталога сценариев)

Смежные вопросы