如何在 pycurl 的 OPENSOCKETFUNCTION 中引发异常

How to raise Exception in OPENSOCKETFUNCTION of pycurl

根据https://curl.haxx.se/libcurl/c/CURLOPT_OPENSOCKETFUNCTION.html, libcurl文档说这个回调可以用于IP地址黑名单,所以我决定用它来屏蔽所有私有IP地址。

我已在我的自定义回调函数中直接尝试 raise Exception,但它不会将任何异常传播到 curl.perform,除非发生超时。

是否可以从 curl.perform() 捕获我在回调函数中引发的异常?

提前致谢。

回调函数是纯C函数,C中没有异常。一个普通的C库,它对异常一无所知。

您可以在此处找到详细信息。gl/SLrKCF

pycurl 可能会在 perform 调用的回调中传播 Python 异常,但这目前尚未实现。现在每个回调都应该 return 一个适当的值来指示错误;在 opensocket 回调的情况下,此值为 CURL_SOCKET_BAD。 (不幸的是,pycurl 目前也没有公开这个常量;请改用 -1。)

提供丰富错误信息的一种方法是将其存储在 Curl 对象本身上,如下所示:

import pycurl, random, socket

class ConnectionRejected(Exception): pass

def opensocket(curl, purpose, curl_address):
    if random.random() < 0.5:
        curl.exception = ConnectionRejected('Rejecting connection attempt in opensocket callback')
        # should be pycurl.SOCKET_BAD in the next release
        return -1

    family, socktype, protocol, address = curl_address
    s = socket.socket(family, socktype, protocol)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
    return s

c = pycurl.Curl()
c.setopt(c.URL, 'http://pycurl.io')
c.exception = None
c.setopt(c.OPENSOCKETFUNCTION,
    lambda purpose, address: opensocket(c, purpose, address))
try:
    c.perform()
except pycurl.error as e:
    if e.args[0] == pycurl.E_COULDNT_CONNECT and c.exception:
        print(c.exception)
    else:
        print(e)

此外,pycurl 目前没有正确处理 -1/CURL_SOCKET_BAD return - 它抱怨 -1 不是有效的 return 值(但功能不受影响). https://github.com/pycurl/pycurl/pull/484 将修复此问题。