1

On trying to download from a https:// URL with PycURL 'PycURL/7.19.3 libcurl/7.35.0 GnuTLS/2.12.23 zlib/1.2.8 libidn/1.28 librtmp/2.3' in Python 2.7 on Ubuntu 14.04.2, I receive

pycurl.error: (35, 'gnutls_handshake() failed: Handshake failed')

curl, however, works fine, maybe due to the fact that it is using openssl:

$ curl --version
curl 7.35.0 (x86_64-pc-linux-gnu) libcurl/7.35.0 OpenSSL/1.0.1f zlib/1.2.8 libidn/1.28 librtmp/2.3

So I would prefer a PycURL binding to openssl too. I tried to reinstall python-pycurl with

export PYCURL_SSL_LIBRARY=openssl
sudo apt-get remove python-pycurl
sudo apt-get install python-pycurl

as is frequenty advised on similar questions, but still pycurl is nor bound to openssl. Same with apt-get remove and easy_install etc.

Question: How to get a PycURL with openssl binding?

Bonus-question: Why is PycURL not installed with openssl binding right away, because the GnuTLS binding seems not to work anyway?

1 Answer 1

2

I was sincerely hoping that this could be resolved without following some instructions which I hardly understand and compiling things and so on. But unfortunately...

See this Gist from 2014 for instructions.

At the time of writing, using Ubuntu Trusty 14.04.2 LTS, the versions are still the same, namely 7.19.3, so the instructions in the Gist can be followed one by one. Spot check was ok and also curl is still working with https://. After stepping through the recipe, pycurl.version shows

PycURL/7.19.3 libcurl/7.35.0 OpenSSL/1.0.1f zlib/1.2.8 libidn/1.28 librtmp/2.3

To automate the downloading, patching and compiling, you will love this little script:

#!/bin/bash

#
#   How to rebuild PycURL against OpenSSL on Ubuntu
#   (tested for 14.04.2 now)
#
#   This script implements the great Gist by aerickson:
#   https://gist.github.com/aerickson/f15133a7e56b2d7f27e3
#   feel free to use it anyway you like.
#   Credits go to Andrew anyway :)
#


# we will add some colored headers that make it easier to find obstacles 
# in the terminal output (which will be > 1000 lines...)
ESC="\x1b["
RESET=$ESC"39;49;00m"
RED=$ESC"31;01m"
GREEN=$ESC"32;01m"
YELLOW=$ESC"33;01m"
BLUE=$ESC"34;01m"

header() {
    echo -e "\n$YELLOW --- $1 --- $RESET\n"
}

echo -e "\n\n$GREEN"
echo -e "\
Build pycurl with openssl support\n\n\
Section numbers refer to\n\
https://gist.github.com/aerickson/f15133a7e56b2d7f27e3
"
echo -e "$RESET\n"



# remove eventually existing pycurl
header "0. remove python-pycurl"
sudo apt-get remove python-pycurl --yes

header "1. install build essentials"
sudo apt-get install build-essential fakeroot dpkg-dev --yes

header "2./3. make build dir"
mkdir ~/python-pycurl-openssl
cd ~/python-pycurl-openssl

if [ ! "$HOME/python-pycurl-openssl" = `pwd` ]; then
    echo -e "\n${RED}Cannot change to working dir. WTF?${RESET}\n"
    exit 1
fi

header "4. get pycurl sources"
sudo apt-get source python-pycurl --yes

header "5. get build dependencies for python-pycurl"
sudo apt-get build-dep python-pycurl --yes

header "6. install libcurl with openssl"
sudo apt-get install libcurl4-openssl-dev --yes

DIR=`find * -name 'pycurl*' -type d -print`
DSC=`find * -name '*.dsc' -type f -print`

echo
echo "DIR = $DIR"
echo "DSC = $DSC"
echo

header "7. unpack source archive"
sudo dpkg-source -x $DSC

header "8. change to package dir"
cd $DIR

header "9. edit debian/control file"
sudo cp debian/control ./control.gnutls
sudo cat ./control.gnutls | sed -e 's|libcurl4-gnutls-dev|libcurl4-openssl-dev|' | sudo tee ./control.openssl >/dev/null
sudo cp ./control.openssl debian/control

header "10. build package"
echo "hold on..."
echo "(crashdump of nosetests is 'normal')"
sudo PYCURL_SSL_LIBRARY=openssl dpkg-buildpackage -rfakeroot -b 2>&1 | sudo tee ../buildlog.txt >/dev/null
echo
echo -e $BLUE
sudo head ../buildlog.txt
echo -e $RESET
echo "   [ ... 1000+ more messages omitted ... ]"
echo -e $BLUE
sudo tail ../buildlog.txt
echo -e $RESET
echo
echo "find more output in ~/python-pycurl-openssl/buildlog.txt:"
wc -l  ../buildlog.txt

header "11. install via package manager"
sudo dpkg -i ../python-pycurl_*.deb

echo
echo "some other packages are available also now:"
ls ../*.deb
echo "they can be installed by 'sudo dpkg -i ../py...' from here."

There is hope, however, that a newer version 7.19.5 will make it to the repos, which is supposed to have the issues fixed in GnuTLS so that PycURL would start to work out of the box. Still the question remains, why this issue is in the repos since 2009 and no one cares...

Update Issues

Funny enough, any subsequent regular Ubuntu update of pycurl/libcurl will overwrite your change. So be prepared to repeat this over and over :(

Alternatively, you can put python-pycurl on hold after building it with openssl to make sure apt-get update will not overwrite it anymore:

sudo apt-mark hold python-pycurl

Updates can be re-enabled later by

sudo apt-mark unhold python-pycurl 

Raspberry Recipe

The above script runs fine on Raspberry Pi with Raspbian Wheezy too, when you add the ability to install sources before by

sudo nano /etc/apt/sources.list

and uncommenting the deb-src line, so that the file will look like

deb http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
deb-src http://archive.raspbian.org/raspbian/ wheezy main contrib non-free rpi

When the sources are not found (in step 4), you might have to do an

sudo apt-get update

before running the above script.

Note: On the Raspberry, the process suffers a bit from the processor speed and you should take aside half an hour (if everything works smoothly). And again, either you put python-pycurl on hold or you will have to invest this half hour again after each update.

1
  • The handshake failure appeared for me when running add-apt-repository. The solution here built pycurl, but removed add-apt-repository. Reinstalling add-apt-repository removed the newly compiled pycurl :/ Aug 16, 2017 at 19:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .