回调

对于更细粒度的控制,libcurl允许与每个连接关联许多回调。在pycurl中,回调是使用 setopt() 具有选项的Curl对象的方法 WRITEFUNCTIONREADFUNCTIONHEADERFUNCTIONPROGRESSFUNCTIONXFERINFOFUNCTIONIOCTLFUNCTIONDEBUGFUNCTION . 这些选项对应于libcurl选项 CURLOPT_ 前缀已删除。pycurl中的回调必须是常规的python函数、类方法或扩展类型函数。

与libcurl回调相比,可以与pycurl回调同时使用的某些选项存在一些限制。这是为了允许不同的回调函数与不同的curl对象相关联。更具体地说, WRITEDATA 不能与一起使用 WRITEFUNCTIONREADDATA 不能与一起使用 READFUNCTIONWRITEHEADER 不能与一起使用 HEADERFUNCTION . 在实践中,这些限制可以通过将回调函数作为类实例方法来克服,而不是使用类实例属性来存储每个对象的数据,例如回调中使用的文件。

下面记录了pycurl中使用的每个回调的签名。

错误报告

pycurl回调调用如下:

python应用程序-> perform() ->libcurl(C代码)->python回调

因为回调是由libcurl调用的,所以它们不应该在失败时引发异常,而是返回指示失败的适当值。下面单独回调的文档指定了预期的成功和失败返回值。

pycurl或python运行时将截获从python回调中传播的未处理异常。这将使回调失败,并具有一般的失败状态,反过来使 perform() 操作。失败 perform() 将提高 pycurl.error ,但使用的错误代码取决于特定的回调。

异常对象等丰富的上下文信息可以以各种方式存储,例如,下面的示例将opensocket回调异常存储在curl对象上:

import pycurl, random, socket

class ConnectionRejected(Exception):
    pass

def opensocket(curl, purpose, curl_address):
    # always fail
    curl.exception = ConnectionRejected('Rejecting connection attempt in opensocket callback')
    return pycurl.SOCKET_BAD

    # the callback must create a socket if it does not fail,
    # see examples/opensocketexception.py

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)

WRITEFUNCTION

WRITEFUNCTION(byte string) number of characters written

用于写入数据的回调。相对应 CURLOPT_WRITEFUNCTION 在俚语中。

在python 3上,参数的类型为 bytes .

这个 WRITEFUNCTION 回调可能返回写入的字节数。如果此数字不等于字节字符串的大小,则表示有错误,libcurl将中止请求。返回 None 是指示回调已消耗传递给它的所有字符串的另一种方法,因此成功了。

write_test.py test 显示如何使用 WRITEFUNCTION .

示例:文档标题和正文的回调

此示例将头数据打印到stderr,体数据打印到stdout。还要注意,回调都不会返回写入的字节数。对于writeFunction和headerFunction回调,返回none意味着写入的所有字节。

## Callback function invoked when body data is ready
def body(buf):
    # Print body data to stdout
    import sys
    sys.stdout.write(buf)
    # Returning None implies that all bytes were written

## Callback function invoked when header data is ready
def header(buf):
    # Print header data to stderr
    import sys
    sys.stderr.write(buf)
    # Returning None implies that all bytes were written

c = pycurl.Curl()
c.setopt(pycurl.URL, "http://www.python.org/")
c.setopt(pycurl.WRITEFUNCTION, body)
c.setopt(pycurl.HEADERFUNCTION, header)
c.perform()

HEADERFUNCTION

HEADERFUNCTION(byte string) number of characters written

用于写入接收头的回调。相对应 CURLOPT_HEADERFUNCTION 在俚语中。

在python 3上,参数的类型为 bytes .

这个 HEADERFUNCTION 回调可能返回写入的字节数。如果此数字不等于字节字符串的大小,则表示有错误,libcurl将中止请求。返回 None 是指示回调已消耗传递给它的所有字符串的另一种方法,因此成功了。

header_test.py test 显示如何使用 WRITEFUNCTION .

READFUNCTION

READFUNCTION(number of characters to read) byte string

用于读取数据的回调。相对应 CURLOPT_READFUNCTION 在俚语中。

在Python3上,回调必须返回字节字符串或仅由ASCII码位组成的Unicode字符串。

此外, READFUNCTION 可能返回 READFUNC_ABORTREADFUNC_PAUSE . 有关这些值的说明,请参阅libcurl文档。

这个 file_upload.py example 在发行版中包含用于 READFUNCTION .

SEEKFUNCTION

SEEKFUNCTION(offset, origin) status

查找操作的回调。相对应 CURLOPT_SEEKFUNCTION 在俚语中。

IOCTLFUNCTION

IOCTLFUNCTION(ioctl cmd) status

用于I/O操作的回调。相对应 CURLOPT_IOCTLFUNCTION 在俚语中。

注: 此回调已被弃用。使用 SEEKFUNCTION 相反。

DEBUGFUNCTION

DEBUGFUNCTION(debug message type, debug message byte string) None

调试信息的回调。相对应 CURLOPT_DEBUGFUNCTION 在俚语中。

在7.19.5.2版中更改: 第二个论点 DEBUGFUNCTION 回调现在是类型 bytes 在Python 3上。以前,参数的类型为 str .

debug_test.py test 显示如何使用 DEBUGFUNCTION .

示例:调试回调

此示例演示如何使用调试回调。调试消息类型是一个整数,指示调试消息的类型。必须启用verbose选项才能调用此回调。

def test(debug_type, debug_msg):
    print("debug(%d): %s" % (debug_type, debug_msg))

c = pycurl.Curl()
c.setopt(pycurl.URL, "https://curl.haxx.se/")
c.setopt(pycurl.VERBOSE, 1)
c.setopt(pycurl.DEBUGFUNCTION, test)
c.perform()

PROGRESSFUNCTION

PROGRESSFUNCTION(download total, downloaded, upload total, uploaded) status

进度表的回调。相对应 CURLOPT_PROGRESSFUNCTION 在俚语中。

PROGRESSFUNCTION 接收作为回调浮点参数的金额。因为libcurl 7.32.0 PROGRESSFUNCTION 被贬低; XFERINFOFUNCTION 应改为使用接收长度为整数的金额。

NOPROGRESS 必须为false libcurl设置选项才能调用进度回调,默认情况下为pycurl设置 NOPROGRESS 成真。

XFERINFOFUNCTION

XFERINFOFUNCTION(download total, downloaded, upload total, uploaded) status

进度表的回调。相对应 CURLOPT_XFERINFOFUNCTION 在俚语中。

XFERINFOFUNCTION 以长整数形式接收金额。

NOPROGRESS 必须为false libcurl设置选项才能调用进度回调,默认情况下为pycurl设置 NOPROGRESS 成真。

示例:下载/上载进度回调

此示例演示如何使用进度回调。下载文档时,与上载相关的参数为零,反之亦然。

## Callback function invoked when download/upload has progress
def progress(download_t, download_d, upload_t, upload_d):
    print("Total to download", download_t)
    print("Total downloaded", download_d)
    print("Total to upload", upload_t)
    print("Total uploaded", upload_d)

c = pycurl.Curl()
c.setopt(c.URL, "http://slashdot.org/")
c.setopt(c.NOPROGRESS, False)
c.setopt(c.XFERINFOFUNCTION, progress)
c.perform()

OPENSOCKETFUNCTION

OPENSOCKETFUNCTION(purpose, address) int

用于打开套接字的回调。相对应 CURLOPT_OPENSOCKETFUNCTION 在俚语中。

目的 是一个 SOCKTYPE_* 价值。

地址 是一个 namedtuple 具有 familysocktypeprotocoladdr 每个字段 CURLOPT_OPENSOCKETFUNCTION 文档。

addr 是表示地址的对象。目前支持以下地址系列:

  • AF_INETaddr 是一个2元组 (host, port) .

  • AF_INET6addr 是一个4元组 (host, port, flow info, scope id) .

  • AF_UNIXaddr 是包含Unix套接字路径的字节字符串。

    可用性:Unix。

此行为与Python的 socket module .

回调应该返回一个socket对象、一个socket文件描述符或一个具有 fileno 包含套接字文件描述符的属性。

回调可以通过调用 setopt 具有 None 作为值或通过调用 unsetopt .

open_socket_cb_test.py test 显示如何使用 OPENSOCKETFUNCTION .

在7.21.5版中更改: 以前,收到的回调 familysocktypeprotocoladdr 参数 (purpose 未通过 address 被压扁了)。也, AF_INET6 地址被公开为 (host, port) 而不是四元组。

在7.19.3版中更改: addr 参数已添加到回调。

CLOSESOCKETFUNCTION

CLOSESOCKETFUNCTION(curlfd) int

用于设置套接字选项的回调。相对应 CURLOPT_CLOSESOCKETFUNCTION 在俚语中。

库尔夫德 是要关闭的文件描述符。

回调应返回 int .

回调可以通过调用 setopt 具有 None 作为值或通过调用 unsetopt .

close_socket_cb_test.py test 显示如何使用 CLOSESOCKETFUNCTION .

SOCKOPTFUNCTION

SOCKOPTFUNCTION(curlfd, purpose) int

用于设置套接字选项的回调。相对应 CURLOPT_SOCKOPTFUNCTION 在俚语中。

库尔夫德 是新创建的套接字的文件描述符。

目的 是一个 SOCKTYPE_* 价值。

回调应返回 int .

回调可以通过调用 setopt 具有 None 作为值或通过调用 unsetopt .

sockopt_cb_test.py test 显示如何使用 SOCKOPTFUNCTION .

SSH_KEYFUNCTION

SSH_KEYFUNCTION(known_key, found_key, match) int

已知主机匹配逻辑的回调。相对应 CURLOPT_SSH_KEYFUNCTION 在俚语中。

known_keyfound_key 是的实例 KhKey 是一个 namedtuple 具有 keykeytype 字段,对应于libcurl的 struct curl_khkey ::

KhKey = namedtuple('KhKey', ('key', 'keytype'))

在python 2上, key 领域 KhKey 是一个 str . 在python 3上, key 字段是 bytes . 键入式 是一个 int .

known_key 可能是 None 当没有已知匹配的主机密钥时。

SSH_KEYFUNCTION 回调应返回 KHSTAT_* 价值。

回调可以通过调用 setopt 具有 None 作为值或通过调用 unsetopt .

ssh_key_cb_test.py test 显示如何使用 SSH_KEYFUNCTION .

TIMERFUNCTION

TIMERFUNCTION(timeout_ms) None

libcurl请求安装定时器的回调。对应于 CURLMOPT_TIMERFUNCTION

应用程序应该安排一个非重复计时器来触发 timeout_ms 毫秒,此时应用程序应调用 socket_actionperform

看见 examples/multi-socket_action-select.py 用于使用计时器函数和套接字函数的示例程序。

SOCKETFUNCTION

SOCKETFUNCTION(what, sock_fd, multi, socketp) None

通知应用程序有关libcurl套接字上的活动的回调。对应于 CURLMOPT_SOCKETFUNCTION

请注意,PycURL回调使用 what 作为第一个参数,并且 sock_fd 作为第二个参数,而libcurl回调采用 sock_fd 作为第一个参数,并且 what 作为第二个论点。

这个 userp (“私有回调指针”)参数,如 CURLMOPT_SOCKETFUNCTION 文档)设置为 CurlMulti 实例。

这个 socketp (“私有套接字指针”)参数,如 CURLMOPT_SOCKETFUNCTION 文档)设置为提供给 assign 方法来创建相应的 sock_fd ,或 None 如果未赋值,则返回。

看见 examples/multi-socket_action-select.py 用于使用计时器函数和套接字函数的示例程序。