2013-06-12 14 views
7

Zajmuję się tworzeniem aplikacji dla OS X. Aplikacja wymaga komunikowania się z serwerem poprzez żądania Pythona, używając bezpiecznego połączenia.SSLError w Żądaniach podczas pakowania jako OS X .app

Jestem w stanie uruchomić plik Pythona, który zamierzam spakować, i to się uda z połączeniem SSL. Jednak, kiedy spakować plik z py2app i spróbować go uruchomić, pojawia się następujący błąd:

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 

udało mi się zapakować część mojego wniosku pomyślnie. Problem zaczyna się, gdy plik docelowy zależy, gdzieś w łańcuchu, na Żądaniach.

Używam zc.buildout do organizowania moich importów. Dlatego używam lokalnego interpretera pythonów tworzonego przez buildout, więc wszelkie poprawki, niestety, będą łatwiejsze do wdrożenia, jeśli nie będą wymagały modyfikacji systemu Python. Jednak wszystkie sugestie są mile widziane i zrobię co w mojej mocy, aby je zmodyfikować zgodnie z moją specyfikacją.

Dzieje się tak tylko po uruchomieniu aplikacji w pakiecie. Jakieś pomysły?

Odpowiedz

6

Obejście easiests jest dodanie opcji dla py2app do pliku setup.py:

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

Obejmuje cały pakiet do pakietu aplikacji, w tym pakiet certyfikatów.

Złożyłem numer issue for this in my py2app tracker, przyszła wersja py2app będzie zawierać logikę do wykrywania użycia biblioteki żądań i automatycznie skopiuje pakiet certyfikatów.

+0

Cześć Ronald, to obejście już nie działa. Czy są jakieś nowości dotyczące aktualizacji do py2app? Dzięki! –

3

Żądania używają pakietu certyfikatów potwierdzających tożsamość serwerów. Ten pakiet jest przechowywany (musi być) w niezależnym pliku. Normalnie żąda statków z własnym pakietem, ale jeśli zostanie spakowany do pojedynczego pliku, pakiet zostanie utracony. Możesz wysłać nowy pakiet wraz z aplikacją lub pozwolić, aby żądania korzystały z certyfikatu ogólnosystemowego. (nie wiem, gdzie OS X przechowuje ten plik, ale na moim Linuksie jego /etc/ssl/certs/ca-certificates.crt)

Aby zobaczyć, gdzie wnioski oczekuje, że plik można to zrobić:

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

Aby zmienić lokalizacja, w których wnioski szuka wiązki można przekazać verify -parameter z wartości ciągu:

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

Jeśli nie chcesz przekazać parametr za każdym razem, stworzyć sesję i skonfigurować go używać wiązkę :

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

Poprzednia zaakceptowana odpowiedź nie była dla mnie odpowiednia - może sposób, w jaki zmieniły się prace zleceń.

Aby rozwiązać ten problem zmieniłem moje setup.py opcje obejmują pakiet Certyfi gdzie plik certyfikatu PEM mieszka:

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

Następnie dodaje to do wniosków Python wywoła:

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

... 

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

ten może być różny w innych wersjach Pythona.

+0

Tak, to był ważny krok także dla mojego pakietu. Dziękuję eAi – Jon

+0

FYI domyślnie mój pakiet zgłoszeń używał pakietu 'certifi' dla' cacert.pem' zamiast własnego, ale 'certifi' znajdował się w pliku sitepackage.zip, a nie w otwartym folderze. Alternatywą może być '' pem_path = "lib/python2.7/wnioski/cacert.pem", jeśli is_py2app inny Brak '' użyć jedną opakowaną z żądaniami (nie wymagających Certyfi być dodane). Ale wyobrażam sobie, że to ma niewielką różnicę. – Jon

+0

Witam @eAi Przykro mi, jeśli to głupie pytanie. Ale czym jest 'sys' w linii' is_py2app = hasattr (sys, "frozen") '? –

0

Wpadłem na ten sam problem i musiałem rozprowadzić moją aplikację do użytkowników, którzy mogą nie mieć Pythona lub pakietu certyfikatów zainstalowanych na swoich komputerach Mac. Opierając się na inspiracjach z odpowiedzi tutaj, wymyśliłem następujące rozwiązanie.

Krok 1: Pobierz pakiet OpenSSL z https://www.openssl.org/source/. Znajdź numer /openssl-1.0.2n/certs/demo/ca-cert.pem i umieść go w tym samym katalogu, co program w języku Python (na przykład main.py).

Krok 2: Utwórz setup.py jak zwykle, ale uwzględnij ca-cert.pem na liście DATA_FILES. Więc setup.py powinien wyglądać mniej więcej tak:

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'], 
) 

Krok 3: Użycie parametru verify więc wnioski użyje pliku certyfikatu podasz.

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

Alternatywnie, można również utworzyć sesji, dzięki czemu nie trzeba określać verify za każdym razem.

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

Krok 4: Spakuj aplikację za pomocą py2app jak zwykle. Wynikowa aplikacja powinna działać normalnie.

python setup.py py2app