SSLError в запросах при упаковке как OS X .app
Я разрабатываю приложение для 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 для организации своего импорта. Поэтому я работаю в локальном интерпретаторе Python, созданном компоновщиком, поэтому любые исправления, к сожалению, будет проще реализовать, если они не предполагают изменение системы Python. Тем не менее, все предложения приветствуются, и я сделаю все возможное, чтобы изменить их для моей специфики.
Это происходит только тогда, когда я запускаю упакованное приложение. Есть идеи?
4 ответа
Обходной путь easyiests - добавить опцию для py2app в ваш файл setup.py:
setup(
...
options={
'py2app':{
'packages': [ 'requests' ]
}
}
)
Это включает в себя весь пакет в комплекте приложений, включая пакет сертификатов.
Я подал проблему для этого в моем трекере py2app, будущая версия py2app будет включать логику для обнаружения использования библиотеки запросов и будет автоматически копировать комплект сертификатов.
Requests использует комплект сертификатов для проверки подлинности сервера. Этот комплект хранится (он должен быть) в отдельном файле. Обычно запрашивает корабли со своим собственным пакетом, но если он упакован в один файл, пакет теряется. Вы можете отправить новый пакет вместе с вашим приложением или позволить запросам использовать общесистемный сертификат.
(Я не знаю, где OS X хранит этот файл, но на моем linux box его /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")
Предыдущий принятый ответ не работал для меня - возможно, способ работы запросов изменился.
Чтобы решить эту проблему, я изменил мои параметры setup.py, чтобы включить пакет certifi, в котором находится файл сертификата pem:
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.
Я столкнулся с той же проблемой, и мне пришлось распространять свое приложение среди пользователей, у которых может не быть установленный 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
как обычно, но включают ca-cert.pem
в списке DATA_FILES. Так что ваши 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