2013-06-12 13 views
7

私はOS X用のアプリケーションを開発しています。アプリケーションには、安全な接続を使用してpython-requestを通じてサーバーと通信する必要があります。OS XとしてパッケージングするときのリクエストでのSSLError .app

私はパッケージ化しようとする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を使用してインポートを整理しています。したがって、ビルドアウトで作成されたローカルのPythonインタプリタで実行しているので、残念ながら、システムPythonを変更する必要がなければ、実装するのが簡単になります。しかし、すべての提案は大歓迎です、私は自分のためにそれらを修正するために全力を尽くします。

これは、パッケージ化されたアプリケーションを実行する場合にのみ発生します。何か案は?

答えて

6

easiestsの回避策は、あなたのsetup.pyファイルにpy2appためのオプションを追加することです:

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

これは、証明書バンドルを含むアプリケーションバンドルにパッケージ全体を、含まれています。

私は issue for this in my py2app trackerを提出しました。py2appの将来のバージョンでは、要求ライブラリの使用を検出するロジックが組み込まれ、証明書バンドルが自動的にコピーされます。

+0

こんにちはロナルド、この回避策はもう機能していないようです。 py2appのアップデートに関するニュースはありますか?ありがとう! –

3

リクエストは、サーバーIDを確認するために証明書のバンドルを使用します。 このバンドルは、独立したファイルに保管されていなければなりません。通常、要求は独自のバンドルとともに出荷されますが、単一のファイルにパッケージ化されていればバンドルは失われます。 新しいバンドルをあなたのアプリと一緒に出荷したり、システム全体の証明書を使用したりすることができます。

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

変更するには、次の要求はあなたがこれを行うことができ、ファイルが期待 (私はOS Xには、このファイルを保存する場所、知っているが、私のLinuxボックスにその/etc/ssl/certs/ca-certificates.crtません)

確認するには、要求は、バンドルを探す場所は、あなたが文字列値でverify -parameterを渡すことができます。

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") 
3

私が以前に受け入れた回答はうまくいかず、リクエストの仕方が変わったかもしれません。これを解決するには

私は、証明書のPEMファイルが住んで認証取得パッケージを含めるように私のsetup.pyのオプションを変更:

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

その後のpython要求にこれを追加呼び出す:

is_py2app = hasattr(sys, "frozen") 
pem_path = "lib/python2.7/certifi/cacert.pem" if is_py2app else None 

... 

requests.get(..., verify=pem_path) 

この他のPythonバージョンでは異なるかもしれません。

+0

はい、これは私のパッケージにとっても重要なステップでした。ありがとうeAi – Jon

+0

FYI私のリクエストパッケージは、デフォルトで 'certifi'パッケージを' cacert.pem'に使用していましたが、 'certifi'はオープンフォルダではなくsite-package.zipにありました。 代替は が '' 'pem_path = "libに/ python2.7 /要求/ cacert.pemの" is_py2app他なし ' '' 要求(認証取得を必要としないで、パッケージ1を使用しないための場合は、追加されるかもしれません)。しかし、それは私が想像するほとんど違いがありません。 – Jon

+0

こんにちは@eAiこれは愚かな質問であればごめんなさい。しかし 'is_py2app = hasattr(sys、" frozen ")'行の 'sys'とは何ですか? –

0

同じ問題が発生し、PythonまたはcertifiパッケージがMacにインストールされていない可能性のあるユーザーにアプリケーションを配布する必要がありました。ここでの答えからインスピレーションを得て、私は以下の解決策を思いつきました。

手順1:OpenSSLパッケージをhttps://www.openssl.org/source/からダウンロードします。 /openssl-1.0.2n/certs/demo/ca-cert.pemを見つけ、Pythonプログラムと同じディレクトリに置きます(たとえば、main.py)。

ステップ2:通常はsetup.pyを作成しますが、DATA_FILESリストにはca-cert.pemが含まれます。

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パラメータを使用しますので、あなたのsetup.pyは、次のようになります。

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 
関連する問題