pipでpycurlのインストールを試みたら、いろいろと足りないものがあったりしたので自前でビルドしました。
前回からの続きです。
pycurlのインストール
必要なライブラリをインストールできたらpip
を使ってpycurl
をインストールします。
一緒にルート証明書のコレクションcertifi
もインストールしておきましょう。
(develop)$ pip install pycurl certifi
これで環境構築ができました。ただし共有ライブラリなどがvirtualenvの中にあるので、Pythonから使えるようにしなければなりません。
一般的には環境変数LD_LIBRARY_PATH
や/etc/ld.so.conf
にパスを設定すると思うのですが、今回は「ホスト環境をできるだけ汚さない」方針のため別の方法で解決をしています。
ctypesによるライブラリのロード
なにもせずにpycurl
をインポートすると「共有ライブラリが見つからない」と言われます。次のようになるはずです。
エラーにならない場合はホスト環境のlibcurl
がロードされているかもしれません。
(develop) $ python
Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pycurl
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: libssl.so.81.3: cannot open shared object file: No such file or directory
これを回避するためpycurl
のインポート前に手動で共有ライブラリをロードします。
ライブラリが配置されている場所は$VIRTUAL_ENV/lib/
ですので次のようにします。
import os
import ctypes
venvdir = os.environ.get('VIRTUAL_ENV')
if venvdir:
ctypes.cdll.LoadLibrary(venvdir+'/lib/libcurl.so')
ここでlibcurl.so
を明示的にロードしてあげると、ほかのライブラリはビルド時に設定したLDFLAGS
の効力で勝手に検索してくれるようです。
HTTP/2の動作確認
virtualenvのPythonを使って以下のスクリプトを実行してみます。
import os
import ctypes
venvdir = os.environ.get('VIRTUAL_ENV')
if venvdir:
ctypes.cdll.LoadLibrary(venvdir+'/lib/libcurl.so')
import pycurl
import certifi
from io import BytesIO
url='https://nghttp2.org/'
def header_function(header_line):
print(header_line)
buffer = BytesIO()
c = pycurl.Curl()
c.setopt(pycurl.HTTP_VERSION, pycurl.CURL_HTTP_VERSION_2)
c.setopt(c.URL, url)
c.setopt(c.HEADERFUNCTION, header_function)
c.setopt(c.WRITEDATA, buffer)
c.perform()
実行するとHTTPレスポンスの内容が表示されます。先頭に
b'HTTP/2 200 \r\n'
の行があればHTTP/2で通信できているはずです。
HTTP/3の動作確認
先ほどと同じく、virtualenvのPythonを使って以下のスクリプトを実行してみます。
import os
import ctypes
venvdir = os.environ.get('VIRTUAL_ENV')
if venvdir:
ctypes.cdll.LoadLibrary(venvdir+'/lib/libcurl.so')
import pycurl
import certifi
from io import BytesIO
url='https://nghttp2.org:4433/'
def header_function(header_line):
print(header_line)
buffer = BytesIO()
c = pycurl.Curl()
c.setopt(pycurl.HTTP_VERSION, pycurl.CURL_HTTP_VERSION_3)
c.setopt(c.URL, url)
c.setopt(c.HEADERFUNCTION, header_function)
c.setopt(c.WRITEDATA, buffer)
c.perform()
実行するとHTTPレスポンスの内容が表示されます。先頭に
b'HTTP/3 200 \r\n'
の行があればHTTP/3で通信できているはずです。
共有ライブラリのロード方法について
今回はできるだけvirtualenv環境に必要なものを押し込んだため、pycurl
モジュールの読み込み前にひと手間必要でした。
もしかしたらvirtualenvのactivate
スクリプトでLD_LIBRARY_PATH
を設定したほうが使いやすいかもしれません。
[おわり]