打包为OS X时的请求中的SSLError .app

时间:2013-06-12 17:55:48

标签: python macos python-requests buildout py2app

我正在为OS X开发一个应用程序。该应用程序涉及使用安全连接通过python请求与服务器通信。

我能够运行我打算打包的python文件,并且它通过SSL连接成功。但是,当我用py2app打包文件并尝试运行它时,我收到以下错误:

Traceback (most recent call last):
File "/Users/yossi/Documents/repos/drunken-octo-nemesis/dist/drunken-octo.app/Contents/Resources/__boot__.py", line 338, in <module>
    _run()
File "/Users/yossi/Documents/repos/drunken-octo-nemesis/dist/drunken-octo.app/Contents/Resources/__boot__.py", line 333, in _run
    exec(compile(source, path, 'exec'), globals(), globals())
File "/Users/yossi/Documents/repos/drunken-octo-nemesis/dist/drunken-octo.app/Contents/Resources/media_test.py", line 16, in <module>
    cmpbl.syncWithCloud()
File "src/compare_book_lists.pyc", line 172, in syncWithCloud
File "src/compare_book_lists.pyc", line 64, in checkMediaOnCloud
File "src/get_cloud_book_list.pyc", line 26, in getCloudFulfilledBookList
File "requests/api.pyc", line 55, in get
File "requests/api.pyc", line 44, in request
File "requests/sessions.pyc", line 354, in request
File "requests/sessions.pyc", line 460, in send
File "requests/adapters.pyc", line 250, in send
requests.exceptions.SSLError: [Errno 185090050] _ssl.c:340: error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib
2013-06-12 11:39:49.119 drunken-octo[1656:707] drunken-octo Error

我能够成功打包部分应用程序。当目标文件在链中的某个位置依赖于请求时,问题就开始了。

我正在使用zc.buildout来组织我的导入。因此,我在buildout创建的本地python解释器中运行,所以如果它们不涉及修改系统Python,那么任何修复都将更容易实现。但是,欢迎提出所有建议,我会尽力根据具体情况对其进行修改。

这只在我运行打包的应用程序时发生。有什么想法吗?

4 个答案:

答案 0 :(得分:6)

最简单的解决方法是将py2app的选项添加到setup.py文件中:

setup(
   ...
   options={
      'py2app':{
          'packages': [ 'requests' ]
       }
   }
)

这包括应用程序包中的整个包,包括证书包。

我已经提交了一份 issue for this in my py2app tracker,py2app的未来版本将包含检测请求库使用的逻辑,并将自动复制证书包。

答案 1 :(得分:3)

请求使用一组ceritificates来验证服务器身份。 该捆绑包(必须是)保存在一个独立的文件中。通常请求船只拥有自己的捆绑包,但如果打包成单个文件,捆绑包就会丢失。 您可以在应用旁边发送新捆绑包,也可以让请求使用系统范围的证书。 (我不知道,OS X保存此文件的位置,但在我的linux框中保存/etc/ssl/certs/ca-certificates.crt

要查看请求文件的位置,您可以执行以下操作:

import requests
print(requests.certs.where())

要更改请求查找捆绑包的位置,您可以使用字符串值传递verify - 参数:

import requests
requests.get("https://httpbin.org/", verify="path/to/your/bundle")

如果您不想每次都传递参数,请创建会话并将其配置为使用您的捆绑包:

import requests
s = requests.Session()
s.verify = "path/to/your/bundle"
s.get("https://httpbin.org")

答案 2 :(得分:3)

之前接受的答案对我不起作用 - 也许请求的工作方式已经改变。

要解决此问题,我更改了我的setup.py选项,以包含证书pem文件所在的certifi包:

        <body>


        <div id='photos'><img src='galerie/backintroju.jpg'id='intro'class='responsivegal'/></div>

        <div id='infosphotos' class='t37'>08:55am&nbsp; July&nbsp; 25 &nbsp;2015, &nbsp; <b id='urk'>Urk </b>&nbsp; (The Netherlands)</div>

        <div id='boutondroite'> <a href='l37.html'><img src='image1/droite.png'class='responsivebouton'/></a> </div>



        <div id='fermer'><a href='photos.html'><img src='image1/fermer3.png'class='responsivebouton'/></a></div>
          </body>

然后将其添加到python请求调用:

OPTIONS = {'argv_emulation': True,'packages': ['certifi']}

在其他Python版本上可能会有所不同。

答案 3 :(得分:0)

我遇到了同样的问题,不得不将我的应用程序分发给可能没有在Mac上安装Python或certifi软件包的用户。借鉴这里答案的灵感,我提出了以下解决方案。

步骤1:从https://www.openssl.org/source/下载OpenSSL包。查找/openssl-1.0.2n/certs/demo/ca-cert.pem并将其放在与Python程序相同的目录下(例如main.py)。

第2步:像往常一样创建setup.py,但在DATA_FILES列表中包含ca-cert.pem。所以你的setup.py应该是这样的:

from setuptools import setup

APP = ['main.py']
DATA_FILES = ['ca-cert.pem']
OPTIONS = {'argv_emulation': False}

setup(
    app=APP,
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)

步骤3:使用verify参数,以便请求将使用您提供的证书文件。

import requests
requests.get("https://httpbin.org/", verify="ca-cert.pem")

或者,您也可以创建会话,这样您就不必每次都指定verify

import requests
s = requests.Session()
s.verify = "ca-cert.pem"
s.get("https://httpbin.org")

步骤4:照常使用py2app打包应用程序。生成的应用程序应该能够正常运行。

python setup.py py2app