如何在pycurl的OPENSOCKETFUNCTION中引发异常

时间:2018-03-08 11:21:24

标签: python libcurl pycurl

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

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

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

提前致谢。

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

pycurl有可能在回调中传播来自perform调用的Python异常,但目前尚未实现。现在每个回调应该返回一个适当的值来表示错误;在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返回 - 它抱怨-1不是有效的返回值(但功能不受其他影响)。 https://github.com/pycurl/pycurl/pull/484将修复此问题。