import fails: 'module' object has no attribute 'SSLContext'
arnisoph opened this issue · comments
$ pip freeze
backports.ssl==0.0.7
PyYAML==3.11
six==1.9.0
wheel==0.24.0
$ python
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 23 2015, 02:52:03)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import backports.ssl as ssl
>>> import socket
>>> context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'SSLContext'
>>>
Any ideas?
I've also seen a report of this from an IMAPClient user (IMAPClient depends on the backports.ssl).
https://bitbucket.org/mjs0/imapclient/issues/196/attributeerror-module-object-has-no
backports.ssl depends on pyOpenSSL. If pyOpenSSL fails to import then SSLContext and a few other names are removed from the backports.ssl package (see https://github.com/alekstorm/backports.ssl/blob/master/backports/ssl/core.py#L699). It seems that pyOpenSSL isn't installed in your environment.
To help confirm, please try the following from a Python shell in the same environment:
from OpenSSL import crypto
from OpenSSL import SSL
the issue is somehow fixed. thanks!
aaaand I had it again, but brew install libffi
on Mac OS fixed the issue for me.
thanks to technomancy/grenchman#21
Great! The IMAPClient user who was having this problem was missing libffi-dev from his Ubuntu Linux system, so it was the same root cause.
Hmm, I have the same issue on Mac OS X El Capitan. I don't use homebrew...
Okay, so the reason for this is:
>>> from OpenSSL import SSL
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "python2.7/site-packages/OpenSSL/__init__.py", line 8, in <module>
from OpenSSL import rand, crypto, SSL
File "python2.7/site-packages/OpenSSL/rand.py", line 11, in <module>
from OpenSSL._util import (
File "python2.7/site-packages/OpenSSL/_util.py", line 6, in <module>
from cryptography.hazmat.bindings.openssl.binding import Binding
File "python2.7/site-packages/cryptography/hazmat/bindings/openssl/binding.py", line 13, in <module>
from cryptography.hazmat.bindings._openssl import ffi, lib
ImportError: dlopen(python2.7/site-packages/cryptography/hazmat/bindings/_openssl.so, 2): Library not loaded: libssl.1.0.0.dylib
Referenced from: python2.7/site-packages/cryptography/hazmat/bindings/_openssl.so
Reason: image not found
This is very similar to this old chestnut that I hit every time I install psycopg2 on OSX:
This Stack Overflow thread has a bunch of related stuff:
So, is this a problem with how backports.ssl and psycopg2 and structured, or is the problem lower down in the Python stack?
So, here's an interesting difference between Python's included _ssl:
$ otool -L .../lib/python2.7/lib-dynload/_ssl.so
.../lib/python2.7/lib-dynload/_ssl.so:
@loader_path/../../libssl.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
@loader_path/../../libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)
Compare that with the problematic one in backports:
$ otool -L lib/python2.7/site-packages/cryptography/hazmat/bindings/_openssl.so
lib/python2.7/site-packages/cryptography/hazmat/bindings/_openssl.so:
libssl.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1225.1.1)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 913.0.0)
If I manually replace libssl.1.0.0.dylib
with an absolute path to libssl.1.0.0.dylib
(and the others like it) using the following, everything works:
install_name_tool -change libssl.1.0.0.dylib /Library/PostgreSQL/9.4/lib/libssl.1.0.0.dylib lib/python2.7/site-packages/cryptography/hazmat/bindings/_openssl.so
install_name_tool -change libcrypto.1.0.0.dylib /Library/PostgreSQL/9.4/lib/libcrypto.1.0.0.dylib
So, how come _ssl.so
that ships with Python uses @loader_path
and it works, but extensions built locally do not? What can we change in the source distribution to cause local compilation to build usable binaries?