2014-01-18 42 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.") 

任何思考這個錯誤到底是怎麼回事??

編輯:

這裏是我的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文件捆綁:

    對於requests模塊,文件cacert.pem位於:

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

    而對於模塊是:

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

    對於他們每個人,你可以把它複製到裏面您的項目(或只是地址),

    And config setup.py用於包括它:

    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選項,這樣你就可以猴子補丁功能twilioget_cert_file

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

請注意,這可能是twilio或甚至py2exePyInstaller的問題。

+0

好的。所以我在setup.py文件中添加了twilio cacert.pem文件。我的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文件的方式,比如模板或者存儲在cacert.pem中的SSL證書。通常這是使用MANIFEST.in自動完成的,但我不確定該項目如何處理它。查看那裏的文檔以獲取更多信息。

2

我曾與twilio和pyinstaller同樣的問題,並能夠通過修改twilio \休息\資源base.py模塊來解決它:

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文件夾中)