在网络应用中,经常会遇到这种情况:一方尝试连接,但另一方由于网络媒介失效或者其他原因无法响应。Python的socket库提供了一个方法,能通过socket.error异常优雅地处理套接字错误。在这个攻略中会举几个例子。 1.8.1 实战演练 我们来编写几个try-except代码块,每个块对应一种可能发生的错误。为了获取用户输入,可以使用argparse模块。这个模块的功能很强大,而不仅是可以使用sys.argv解析命令行参数。这些try-except代码块分别演示了常见的套接字操作,例如创建套接字对象、连接服务器、发送数据和等待应答。 下述攻略使用几行代码演示了如何处理异常。 代码清单1-7展示了如何处理socket.error异常,如下所示: #!/usr/bin/env python # Python Network Programming Cookbook -- Chapter – 1 # This program is optimized for Python 2.7. It may run on any # other Python version with/without modifications. import sys import socket import argparse def main(): # setup argument parsing parser = argparse.ArgumentParser(description='Socket Error Examples') parser.add_argument('--host', action="store", dest="host", required=False) parser.add_argument('--port', action="store", dest="port", type=int, required=False) parser.add_argument('--file', action="store", dest="file", required=False) given_args = parser.parse_args() host = given_args.host port = given_args.port filename = given_args.file # First try-except block -- create socket try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, e: print "Error creating socket: %s" % e sys.exit(1) # Second try-except block -- connect to given host/port try: s.connect((host, port)) except socket.gaierror, e: print "Address-related error connecting to server: %s" % e sys.exit(1) except socket.error, e: print "Connection error: %s" % e sys.exit(1) # Third try-except block -- sending data try: s.sendall("GET %s HTTP/1.0rnrn" % filename) except socket.error, e: print "Error sending data: %s" % e sys.exit(1) while 1: # Fourth tr-except block -- waiting to receive data from remote host try: buf = s.recv(2048) except socket.error, e: print "Error receiving data: %s" % e sys.exit(1) if not len(buf): break # write the received data sys.stdout.write(buf) if __name__ == '__main__': main() 1.8.2 原理分析 在Python中,可以使用argparse模块把命令行参数传入脚本以及在脚本中解析命令行参数。这个模块在Python 2.7中可用。如果使用较旧版本的Python,这个模块可以到“Python包索引”(Python Package Index,简称PyPI)中获取,使用easy_install或pip安装。 这个攻略用到了三个命令行参数:主机名、端口号和文件名。上述脚本的使用方法如下: $ python 1_7_socket_errors.py –host=<HOST> --port=<PORT> --file=<FILE> 如果提供的主机不存在,这个脚本会输出如下错误: $ python 1_7_socket_errors.py --host=www.pytgo.org --port=8080 --file=1_7_socket_errors.py Address-related error connecting to server: [Errno -5] No address associated with hostname 如果某个端口上没有服务,你却尝试连接到这个端口,则这个脚本会抛出连接超时异常,如下所示: $ python 1_7_socket_errors.py --host=www.python.org --port=8080 --file=1_7_socket_errors.py 这个命令会返回如下错误,因为主机www.python.org监听的不是端口8080: Connection error: [Errno 110] Connection timed out 不过,如果向正确的主机、正确的端口发起随意的请求,应用层可能无法捕获这一异常。例如,运行下述脚本,不会返回错误,但输出的HTML代码说明了脚本的问题: $ python 1_7_socket_errors.py --host=www.python.org --port=80 --file=1_7_socket_errors.py HTTP/1.1 404 Not found Server: Varnish Retry-After: 0 content-type: text/html Content-Length: 77 Accept-Ranges: bytes Date: Thu, 20 Feb 2014 12:14:01 GMT Via: 1.1 varnish Age: 0 Connection: close <html> <head> <title> </title> </head> <body> unknown domain: </body></html> 这个攻略用到了四个try-except块。除第二个块处理socket.gaierror异常之外,其他块都处理socket.error异常。socket.gaierror是地址相关的错误。除此之外还有两种异常:socket.herror,C API中抛出的异常;如果在套接字中使用settimeout()方法,套接字超时后会抛出socket.timeout异常。
Python网络编程攻略——1.8 优雅地处理套接字错误
书名: Python网络编程攻略
作者: 萨卡尔
出版社: 人民邮电出版社
译者: 安道
出版年: 2014-12-1
页数: 170
定价: 45.00元
装帧: 平装
丛书: 图灵程序设计丛书
ISBN: 9787115372697