杰瑞科技汇

Python urllib2 如何设置超时?

核心要点

urllib2 中设置超时,主要是通过 urllib2.urlopen() 函数的 timeout 参数来实现的,这个参数的单位是


基本用法

当你调用 urllib2.urlopen() 时,可以传入一个 timeout 值,如果在指定的时间内,服务器没有响应,或者下载没有完成,程序就会抛出一个 urllib2.URLError 异常。

代码示例

下面是一个简单的例子,设置超时为 5 秒。

import urllib2
import socket
# 目标URL,我们可以使用一个响应较慢的网站来测试
# 或者使用一个不存在的域名来模拟连接超时
url = "http://httpbin.org/delay/10"  # 这个URL会延迟10秒才响应
# 设置超时为5秒
timeout_seconds = 5
try:
    print "正在尝试连接 %s,超时设置为 %d 秒..." % (url, timeout_seconds)
    # 打开URL,并设置超时
    response = urllib2.urlopen(url, timeout=timeout_seconds)
    # 如果成功,读取内容
    html = response.read()
    print "连接成功!获取到 %d 字节的数据。" % len(html)
except urllib2.URLError as e:
    # 处理URL相关的错误,比如连接超时、域名不存在等
    print "连接失败!发生 URLError:"
    if isinstance(e.reason, socket.timeout):
        print "  错误原因: 连接超时"
    else:
        print "  错误原因:", e.reason
except socket.timeout:
    # 底层的socket会直接抛出 timeout 异常
    # 这是一个更具体的异常,可以单独捕获
    print "连接失败!发生 socket.timeout 异常"
except Exception as e:
    # 捕获其他所有可能的异常
    print "发生未知错误:", e

代码解析

  1. try...except:这是处理网络请求中可能出现的错误的最佳实践,网络请求非常不稳定,必须要有异常处理。
  2. urllib2.urlopen(url, timeout=5):这是核心,我们向 urlopen 传递了 timeout=5 参数。
  3. urllib2.URLError:当 urllib2 遇到网络问题时,会抛出这个异常,它有一个 reason 属性,可以告诉我们具体的错误原因。
  4. socket.timeout:这是一个更底层的异常,当底层的 socket 操作(连接或读取)超时时,可能会直接抛出这个异常,将它放在 URLError 之前捕获,可以更精确地处理超时情况。
  5. 测试URLhttp://httpbin.org/delay/10 是一个非常方便的测试工具,它会故意延迟10秒再返回响应,我们设置5秒的超时,必然会触发超时异常,方便我们测试代码。

不同类型的超时

urllib2timeout 参数的行为取决于你设置的值:

  • timeout = None (默认值):不设置超时,程序会无限期地等待下去,直到服务器响应或发生其他错误。在生产环境中应避免这样做,因为它可能导致你的程序永久挂起。
  • timeout = x (x > 0):设置一个正数,这表示连接和读取的总超时时间。
    • 连接超时:在 x 秒内,客户端无法与服务器建立连接。
    • 读取超时:连接已经建立,但在 x 秒内,客户端没有从服务器接收到任何数据。
    • urllib2timeout 参数是这两个阶段的总和,它不是一个独立的连接超时或读取超时。

requests 库的对比

虽然 urllib2 是 Python 的标准库,但现代 Python 开发中,更推荐使用第三方库 requestsrequests 的 API 更简洁,并且在处理超时方面更灵活。

requests 设置超时

requests 允许你分别设置连接超时和读取超时。

import requests
url = "http://httpbin.org/delay/10"
try:
    # (连接超时, 读取超时) = (3.05, 27)
    # 或者只设置一个值,它将同时用于连接和读取
    response = requests.get(url, timeout=(3.05, 27))
    print "连接成功!"
    response.raise_for_status() # 如果状态码不是200,则抛出异常
except requests.exceptions.Timeout as e:
    print "请求超时:", e
except requests.exceptions.RequestException as e:
    print "请求发生错误:", e

为什么 requests 更好?

  1. 灵活性:可以分别控制连接和读取超时,这对于精细控制网络行为非常有用。
  2. 易用性:API 设计更符合人类直觉,response.json() 直接解析JSON,response.status_code 获取状态码。
  3. 功能更强大:内置了 Session、Cookie 处理、文件上传等高级功能。

最佳实践和注意事项

  1. 总是设置超时:除非你有特殊需求,否则在所有网络请求中都应设置一个合理的超时时间,防止你的程序因网络问题而卡死。
  2. 妥善处理异常:网络是不可靠的,必须用 try...except 块来包裹你的网络请求代码。
  3. 选择合适的超时时间:超时时间不宜过短(例如1秒),对于正常的网络请求可能不够;也不宜过长(例如60秒),会降低程序的响应速度,5-30 秒是一个比较合理的范围,可以根据你的应用场景调整。
  4. 考虑使用 requests:对于新项目,强烈建议直接使用 requests 库,它更强大、更易用,是事实上的标准。urllib2 主要用于不希望安装第三方依赖的简单脚本或环境。
特性 urllib2 requests
设置超时 urlopen(url, timeout=5) requests.get(url, timeout=5)timeout=(conn, read)
超时类型 连接和读取的总超时 可分别设置连接超时和读取超时
异常处理 urllib2.URLError, socket.timeout requests.exceptions.Timeout, requests.exceptions.RequestException
易用性 较低,API略显繁琐 高,API简洁直观
推荐度 仅在不允许安装第三方库时使用 强烈推荐,现代Python开发的标配

希望这个详细的解释能帮助你完全理解在 Python 中使用 urllib2 处理超时的方法!

分享:
扫描分享到社交APP
上一篇
下一篇