[id_700861631]id_239187423]
为了实现更精密的操作,libcurl能够为各个连接绑定多个回调函数,以此达成目的。在pycurl里,回调是通过setopt()这个Curl对象的方法来设置的,具体包括WRITEFUNCTION,READFUNCTION,HEADERFUNCTION,PROGRESSFUNCTION,XFERINFOFUNCTION,IOCTLFUNCTION以及DEBUGFUNCTION这些选项,它们分别对应于libcurl选项中CURLOPT_前缀被移除的部分。pycurl所要求的回调函数,必须是普通的Python函数,或者是类的成员方法,亦或是扩展类型定义的函数。
pycurl回调和libcurl回调之间,部分选项的兼容性存在差异,这种差异旨在使不同的回调函数能够分别绑定到各自的curl对象上。更详细地讲,WRITEDATA不能和WRITEFUNCTION配合使用,READDATA不能和READFUNCTION配合使用,WRITEHEADER不能和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(拒绝接受连接请求于开放套接字回调过程中) return pycurl.SOCKET_BAD 回调函数需要建立套接字,前提是它没有出现错误 查看示例中的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
写入函数处理字节字符串,返回已写入字符的总数
数据写入时调用的接口,与俗称的 CURLOPT_WRITEFUNCTION 对应。
在python 3上,参数的类型为 bytes .
这个回调函数 WRITEFUNCTION 可能有返回值,代表写入的字节量。若这个值与字节字符串的长度不一致,就说明出现了问题,libcurl会终止当前请求。当回调函数返回 None 时,也意味着它已经处理完所有传入的字符串,这种情况表示操作成功。
编写测试代码时,可以了解运用 WRITEFUNCTION 的方法,具体实例在名为 write_test.py 的文件中呈现,该文件展示了其使用方式。
示例:文档标题和正文的回调
这个范例把头部信息输出到标准错误,把主体信息输出到标准输出,必须留意,所有回调都不会返回写入的字符量。针对writeFunction和headerFunction回调,返回空值表示所有字符已写入完成。
调用回调函数时,表示主体数据已经获取完毕 def body(buf): # Print body data to stdout import sys sys.stdout.write(buf) 返回空表示所有字节均已写入 调用回调函数时,表明头部数据已经获取完毕 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
对字节字符串执行头部函数处理,能够生成对应的字符计数结果
用作填写接收头信息的函数,与俗称中的 CURLMOPT_WRITEFUNCTION 相对应。
在python 3上,参数的类型为 bytes .
这个回调函数 HEADERFUNCTION 可能会返回写入的字节数量。如果这个数量不等于字节字符串的体积,就意味着出现了问题,libcurl会终止当前请求。返回空值 None 也是一种成功的方式,它表明回调已经处理完了所有传递给它的数据。
头部测试文件测试展示了怎样运用写入功能函数。
READFUNCTION
读取指定数量的字符,转换成字节串
处理数据输入的函数,即人们常说的那个读取操作的回调函数。
在Python3环境中,回调函数的输出要求为字节字符串,或者是仅由ASCII码位构成的Unicode字符串。
另外,READFUNCTION函数或许会得出READFUNC_ABORT这个结果,或者给出READFUNC_PAUSE这个结果。想了解这些结果的详细情况,可以查阅libcurl的相关文档。
这个名为 file_upload.py 的范例包含在发行版里,其目的是用于 READFUNCTION 功能。
SEEKFUNCTION
查询函数以偏移量和原始值为参数,返回状态信息
搜索任务的处理函数,与民间说法中的 CURLOPT_SEEKFUNCTION 对应。
IOCTLFUNCTION
执行特定控制命令,返回操作结果
执行输入输出任务的回调函数,其功能等同 API 中名为 CURLOPT_IOCTLFUNCTION 的选项,在行话里俗称这一用法。
注: 此回调已被弃用。使用 相反。
DEBUGFUNCTION
调试功能调试信息类型,调试信息字节串,无返回值
调试信息的返回函数,这相当于配置选项中的调试功能回调地址。
在7.19.5.2版本里调整:第二个论点 DEBUGFUNCTION 回调现在其参数为 bytes 类型,在Python 3环境下。此前,该参数的类型是 str。
执行 debug_test.py 测试程序,可以了解 DEBUGFUNCTION 的具体应用方法。
示例:调试回调
这个例子说明怎样运用调试过程中的回调功能,调试信息的种类是一个数字,它表明了调试信息的性质,只有当详细输出模式被打开时,才能使用这个回调。
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
进度函数接收下载总数据量、已下载数据量、上传总数据量、已上传数据量四个参数,然后返回当前状态
进度更新的通知。这就是所谓的 CURL 设置中的回调函数。
PROGRESSFUNCTION 需要一个浮点数作为回调参数。由于libcurl 7.32.0版本中PROGRESSFUNCTION的功能被弱化,现在应该改为使用一个整数长度的参数,来替代XFERINFOFUNCTION。
调用进度回调前,必须将长句拆分成多个小分句,用逗号隔开,并设置 libcurl 的 NOPROGRESS 为假,因为 pycurl 默认将其设为真。
XFERINFOFUNCTION
传输信息函数包含下载总量,已下载部分,上传总量,已上传部分,并返回状态
进度汇报的响应机制,等同那个叫作 XFERINFOFUNCTION 的选项在行话里的说法
XFERINFOFUNCTION 以长整数形式接收金额。
NOPROGRESS 必须为false libcurl设置选项才能调用进度回调,默认情况下为pycurl设置 NOPROGRESS 成真。
示例:下载/上载进度回调
这个例子说明怎样运用过程反馈功能,文件下载期间,涉及上传的那些数据都是空白,而当进行上传操作时,与此下载有关的数值则没有值。
回调函数在下载或上传过程中有进展时被调用 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
调用开放套接字功能,指定用途,目标地址,返回一个整数值
执行创建套接字的函数。这对应着配置选项名中的特定标识符。
目的 是一个 SOCKTYPE_* 价值。
地址由多个字段构成,其中包括 family, socktype, protocol, 以及 addr。这些字段都属于 CURLOPT_OPENSOCKETFUNCTION 文档。
addr 是表示地址的对象。目前支持以下地址系列:
此行为与Python的 socket module .
回调函数需要提供一个套接字实例、一个套接字文件标识号,或者一个属性,这个属性里包含着 fileno 字段,该字段存储着套接字的文件标识号。
回调可以通过调用 具有 None 作为值或通过调用 .
open_socket_cb_test.py 测试展示了怎样运用 OPENSOCKETFUNCTION 。
在7.21.5版本里做了调整:原先,接收到的回调参数包括 family, socktype, protocol 以及 addr,但 purpose 没有通过 address 被压缩成块。此外,AF_INET6 地址以 host 和 port 的形式公开,而不是四元组。
在7.19.3版中更改: addr 参数已添加到回调。
CLOSESOCKETFUNCTION
关闭套接字功能 curlfd,返回一个整数值
设置套接字参数的函数,与俗称中的 CLOSESOCKETFUNCTION 对应,用于回调操作。
库尔夫德 是要关闭的文件描述符。
回调应返回 int .
回调可以通过调用 具有 None 作为值或通过调用 .
该文件测试展示怎样运用 CLOSESOCKETFUNCTION 函数。
SOCKOPTFUNCTION
SOCKOPTFUNCTION调用curlfd参数, 执行purpose参数指定的功能, 返回一个整数值
设置套接字参数的函数,它对应着俚语中的 CURLOPT_SOCKOPTFUNCTION。
库尔夫德 是新创建的套接字的文件描述符。
目的 是一个 SOCKTYPE_* 价值。
回调应返回 int .
回调可以通过调用 具有 None 作为值或通过调用 .
这个文件名为sockopt_cb_test.py的测试展示了怎样运用SOCKOPTFUNCTION这个功能。
SSH_KEYFUNCTION
SSH密钥功能处理已知密钥,查找匹配密钥,返回比较结果,类型为整数值
识别设备符合规则的响应函数,这对应着所谓的 SSH 密钥回调选项
known_key 与 found_key 是 KhKey 的具体对象,KhKey 是一种结构体,包含 key 和 keytype 两个属性,这些属性与 libcurl 中的 curl_khkey 结构相对应
KhKey = namedtuple('KhKey', ('key', 'keytype'))
在python 2版本中,key字段名为KhKey,其数据类型为字符串类型。在python 3版本中,key字段名同样是KhKey,但数据类型变成了字节类型。键入式字段的数据类型为整型。
已知匹配的主机密钥不存在时,known_key 有可能为空值。
SSH_KEYFUNCTION 回调需要给出 KHSTAT_* 类型的结果。
回调可以通过调用 具有 None 作为值或通过调用 .
ssh_key_cb_test.py 测试展示 SSH_KEYFUNCTION 的应用方式。
TIMERFUNCTION
计时器函数接收超时毫秒数,不返回任何值
libcurl需要安装定时器的回调函数,这个选项叫做CURLMOPT_TIMERFUNCTION。
软件需设定一个独一无二的计时装置,在经过 timeout_ms 秒之后启动,届时软件须执行 或 的操作。
注意到 examples/multi-socket_action-select.py 这个示例程序,它展示了如何运用计时器函数和套接字函数。
SOCKETFUNCTION
创建函数处理参数what, 使用文件描述符sock_fd, 接收多路复用参数multi, 处理socket指针socketp, 不返回任何值
告知通知软件关于libcurl套接字活动的情况,这等同于CURLMOPT_SOCKETFUNCTION选项。
PycURL的回调函数以 what 为首个参数项,同时将 sock_fd 作为次序参数项,而 libcurl的回调函数则将 sock_fd 放在首位,what 放在后续位置。
这个名为 userp 的参数,其含义是“私有回调指针”,在 CurlMulti 实例中,应将其设定为 CURLMOPT_SOCKETFUNCTION 文档所描述的值
这个 socketp 参数,即“私有套接字指针”,依据 CURLMOPT_SOCKETFUNCTION 文档所述,若指定给方法,则用于生成相应的 sock_fd,若未指定,则返回 None。
看见 examples/multi-socket_action-select.py 用于使用计时器函数和套接字函数的示例程序。
还没有评论,来说两句吧...