目录
一、Web 请求与响应基础
(一)Web 请求与响应的定义与组成
(二)HTTP 协议概述
(三)常见的 HTTP 状态码
二、Python 的 requests 库
(一)安装 requests 库
(二)发送 GET 请求
(三)发送 POST 请求
(四)处理响应头和状态码
(五)发送带查询参数的 GET 请求
(六)发送带表单数据的 POST 请求
三、处理 JSON 响应
四、文件操作
(一)打开文件的模式
(二)读取文件
(三)写入文件
(四)下载文件示例
(五)文件操作中的注意事项
(六)其他常用文件操作
五、错误处理与异常捕获
(一)try 语句的使用
(二)示例:捕获常见异常
(三)异常处理总结
六、try语句
(一) 基本语法与结构
(二)捕获多种异常
( 三)捕获所有异常
(四)主动抛出异常(raise)
(五)自定义异常
(六)异常链(raise ... from)
( 七)上下文管理器(with 语句)
(八) 常见异常类型
(九)最佳实践
(十)异常处理流程
(十一) 高级用法:try-except-else-finally 组合
(十二)异常与性能
Web 请求与响应是 Web 通信的基础,其中 Web 请求由客户端发起,服务器处理后返回响应。
Web 请求的组成
Web 响应的组成
HTTP(Hypertext Transfer Protocol)是 Web 上传输数据的协议,负责浏览器与服务器之间的通信。以下是常见的 HTTP 方法:
在使用 requests 库之前,需要先进行安装。如果你的系统中已经安装了 Python 的包管理工具 pip,可以通过以下命令在命令行中安装:
pip install requests
GET 请求通常用于获取数据,我们可以通过 requests.get () 方法来发送 GET 请求,并处理返回的响应。以下是一个简单的示例代码:
import requests
# 发送GET请求
response = requests.get("https://www.example.com")
# 输出响应的状态码
print("Status Code:", response.status_code)
# 输出响应的内容
print("Response Body:", response.text)
# 输出响应头
print("Response Headers:", response.headers)
# 获取响应内容的长度
print("Content Length:", len(response.text))
代码解释:
requests.get()
用于发送 GET 请求,括号内传入要请求的 URL,该方法会返回一个 Response 对象,包含了服务器返回的所有信息。response.status_code
用于获取 HTTP 响应状态码,通过该状态码可以判断请求是否成功。response.text
用于获取响应的正文内容,通常是 HTML 或 JSON 数据,返回的是字符串类型。response.headers
用于获取响应头,它是一个类似字典的对象,可以通过键来访问相应的值。len(response.text)
用于返回响应正文的长度,通过该值可以帮助我们了解返回内容的大小。POST 请求用于将数据提交到服务器,通常用于表单提交或上传文件等场景,我们使用 requests.post () 方法来发送 POST 请求。以下是示例代码:
import requests
# 发送POST请求
url = "https://httpbin.org/post"
data = {"name": "Alice", "age": 25}
response = requests.post(url, data=data)
# 输出响应状态码
print("Status Code:", response.status_code)
# 输出响应内容(JSON格式)
print("Response Body:", response.json())
代码解释:
requests.post()
用于发送 POST 请求,第一个参数是 URL,第二个参数 data 是一个字典,包含了要提交的数据。requests 库会自动将其编码为application/x-www-form-urlencoded
格式。response.json()
用于解析返回的 JSON 数据,它会将 JSON 格式的响应内容转换为 Python 的字典或列表等数据结构,方便我们进行处理。响应头提供了关于服务器的信息,状态码则告诉我们请求是否成功。我们可以通过以下代码来获取响应头和状态码:
import requests
# 发送GET请求
response = requests.get("https://www.example.com")
# 获取响应头
print("Response Headers:", response.headers)
# 获取响应状态码
print("Status Code:", response.status_code)
# 获取内容类型
print("Content - Type:", response.headers.get("Content - Type"))
代码解释:
response.headers
返回响应头,其中包含了如 Content - Type、Date、Server 等信息,我们可以通过字典的 get () 方法来获取指定键的值,如获取内容类型。response.status_code
返回 HTTP 状态码,通过判断该状态码是否为 200 等成功状态码,可以确定请求是否成功执行。在 GET 请求中,我们可以通过 URL 传递查询参数。例如,访问一个包含参数的 URL,我们可以通过 requests.get () 方法的 params 参数来传递查询参数。以下是示例代码:
import requests
# 发送带查询参数的GET请求
url = "https://httpbin.org/get"
params = {"name": "Alice", "age": 25}
response = requests.get(url, params=params)
# 输出响应内容
print("Response Body:", response.json())
代码解释:
params
是一个字典,包含了要传递的查询参数。requests.get () 方法会自动将这些参数编码到 URL 中,生成的 URL 类似于 “https://httpbin.org/get?name=Alice&age=25”。POST 请求可以用来提交表单数据,以下是使用 requests 发送带表单数据的 POST 请求的示例代码:
import requests
# 发送带表单数据的POST请求
url = "https://httpbin.org/post"
data = {"username": "testuser", "password": "mypassword"}
response = requests.post(url, data=data)
# 输出响应的内容
print("Response Body:", response.json())
代码解释:
data
参数是一个字典,包含了表单提交的数据,requests 库会自动将数据编码为application/x-www-form-urlencoded
格式,该格式是表单数据提交的常见格式。许多 Web API 返回的数据格式是 JSON,Python 的 requests 库提供了方便的 JSON 处理方法。以下是示例代码:
import requests
# 发送GET请求并获取JSON响应
url = "https://api.github.com/users/octocat"
response = requests.get(url)
# 解析JSON数据
data = response.json()
# 输出用户的GitHub信息
print("User Login:", data["login"])
print("User Name:", data["name"])
代码解释:
response.json()
方法会将响应的内容解析为 Python 字典,这样我们就可以像操作普通字典一样方便地处理 JSON 数据,通过键来获取相应的值。Python 使用内置的 open () 函数来打开文件,打开文件时需要指定文件模式(即操作文件的方式)。以下是常见的文件打开模式:
以下是使用不同模式打开文件的示例代码:
# 以只读模式打开文件
with open('example.txt', 'r') as file:
content = file.read()
print(content)
# 以写入模式打开文件,文件内容会被覆盖
with open('example.txt', 'w') as file:
file.write("这是新的文件内容。\n")
# 以追加模式打开文件,新的内容会追加到文件末尾
with open('example.txt', 'a') as file:
file.write("追加的内容。\n")
# 以二进制模式打开文件(例如读取图片)
with open('image.jpg', 'rb') as file:
binary_data = file.read()
print("读取到的二进制数据:", binary_data[:20])
Python 中的文件读取功能非常强大,以下是几种常见的读取方式:
with open('example.txt', 'r') as file:
content = file.read()
print(content)
with open('example.txt', 'r') as file:
line = file.readline()
while line:
print(line.strip()) # strip()用来去除行末的换行符
line = file.readline()
with open('example.txt', 'r') as file:
lines = file.readlines()
for line in lines:
print(line.strip())
Python 提供了几种方法将数据写入文件,写入操作常用于日志记录、数据导出等场景。
with open('output.txt', 'w') as file:
file.write("这是第一行数据。\n")
file.write("这是第二行数据。\n")
lines = ["第一行数据。\n", "第二行数据。\n", "第三行数据。\n"]
with open('output.txt', 'w') as file:
file.writelines(lines)
我们可以通过 requests 库来下载文件,并将其保存到本地。以下是下载一个图片文件的示例代码:
import requests
url = "https://www.example.com/image.jpg" # 图片URL
response = requests.get(url)
# 检查请求是否成功
if response.status_code == 200:
# 使用二进制模式写入文件
with open('downloaded_image.jpg', 'wb') as file:
file.write(response.content)
print("图片下载成功!")
else:
print(f"下载失败,状态码:{response.status_code}")
代码解释:
import os
if os.path.exists('example.txt'):
with open('example.txt', 'r') as file:
content = file.read()
else:
print("文件不存在!")
try:
with open('readonly_file.txt', 'w') as file:
file.write("尝试写入只读文件")
except PermissionError:
print("权限不足,无法写入文件。")
import os
file_path = 'example.txt'
print("文件大小:", os.path.getsize(file_path), "字节")
print("文件修改时间:", os.path.getmtime(file_path))
import os
file_path = 'example.txt'
if os.path.exists(file_path):
os.remove(file_path)
print(f"{file_path}已删除!")
else:
print("文件不存在!")
在进行 Web 请求时,可能会发生各种错误,例如网络超时、服务器错误等。requests 库通过异常处理机制帮助我们捕获这些错误,Python 的 try 语句能够捕获和处理代码块中的异常,从而避免程序崩溃,并且提供了处理错误的机会。
try 语句用于捕获和处理异常,它由以下三部分组成(其中 else 块和 finally 块可选):
以下是捕获常见异常的示例代码:
import requests
from requests.exceptions import RequestException, Timeout, HTTPError
try:
# 发送GET请求,并设置超时时间为5秒
response = requests.get("https://www.example.com", timeout=5)
# 如果状态码不是200,抛出HTTPError异常
response.raise_for_status() # 如果状态码是4xx或5xx,抛出异常
# 如果请求成功,则输出响应内容
print("Response Body:", response.text)
# 捕获请求超时异常
except Timeout:
print('Request timed out')
# 捕获HTTP错误(如状态码404、500等)
except HTTPError as http_err:
print(f'HTTP error occurred: {http_err}')
# 捕获其他网络相关的错误
except RequestException as req_err:
print(f'Request error occurred: {req_err}')
# 可以在finally块中清理资源(如关闭文件或连接)
finally:
print("Request attempt completed.")
代码解释:
except 块:
finally 块:其中的代码无论是否发生异常都会被执行,这里仅打印 “Request attempt completed.”,用于表示请求的结束,通常在此处可以进行一些资源清理工作,如关闭文件、数据库连接等,确保程序的资源得到合理释放。
try:
# 可能引发异常的代码块
result = 10 / 0 # 除零错误
except ZeroDivisionError as e:
# 捕获特定异常并获取错误对象
print(f"错误: {e}") # 输出: division by zero
else:
# 仅在 try 块无异常时执行
print("计算成功:", result)
finally:
# 无论是否异常都执行(常用于资源清理)
print("执行完毕")
1 .分别处理不同异常
try:
num = int("abc") # ValueError
result = 10 / num # ZeroDivisionError
except ValueError:
print("输入不是有效整数")
except ZeroDivisionError:
print("除数不能为零")
2 .合并处理同类异常
try:
file = open("nonexistent.txt") # FileNotFoundError
data = json.load(file) # JSONDecodeError
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"文件错误: {e}")
⚠️ 不推荐滥用,可能掩盖严重问题:
try:
# 任意代码
except Exception as e:
print(f"未知错误: {e}")
# 推荐记录堆栈信息用于调试
import traceback
print(traceback.format_exc())
raise
)def validate_age(age):
if age < 0:
raise ValueError("年龄不能为负数")
return age
try:
validate_age(-5)
except ValueError as e:
print(e) # 输出: 年龄不能为负数
class AuthError(Exception):
"""自定义认证错误"""
def __init__(self, message="认证失败"):
self.message = message
super().__init__(self.message)
# 使用示例
try:
if not user_authenticated():
raise AuthError("无效令牌")
except AuthError as e:
print(f"认证异常: {e}")
raise ... from
)保留原始异常信息,便于定位问题:
try:
data = json.loads("invalid json")
except json.JSONDecodeError as e:
raise RuntimeError("配置解析失败") from e
输出:
Traceback (most recent call last):
File "", line 2, in
json.JSONDecodeError: Expecting value...
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "", line 4, in
RuntimeError: 配置解析失败
with
语句)替代 try-finally
进行自动资源管理:
try:
with open("data.txt", "r") as file:
content = file.read()
except FileNotFoundError:
print("文件不存在")
# 文件会自动关闭,无需手动调用 file.close()
异常类型 | 触发场景 |
---|---|
ZeroDivisionError |
除零错误 |
TypeError |
类型不匹配(如字符串 + 整数) |
ValueError |
值不符合预期(如 int("abc") ) |
FileNotFoundError |
文件不存在 |
KeyError |
字典键不存在 |
IndexError |
索引越界 |
PermissionError |
权限不足 |
TimeoutError |
操作超时 |
1 .精确捕获异常
try:
result = 10 / num
except (ZeroDivisionError, TypeError) as e:
print(f"计算错误: {e}")
2 .使用 logging
记录异常
import logging
try:
# 危险操作
except Exception as e:
logging.error(f"系统异常: {e}", exc_info=True)
3 .自定义异常分层
class AppError(Exception):
"""应用基础异常"""
class DatabaseError(AppError):
"""数据库操作异常"""
class ConnectionError(DatabaseError):
"""连接异常"""
4 .资源清理优先用 with
# 不推荐
file = open("data.txt")
try:
data = file.read()
finally:
file.close()
# 推荐
with open("data.txt") as file:
data = file.read()
try
块:若有异常,跳转到第一个匹配的 except
except
:按顺序检查,找到则执行对应代码块else
:若 try
无异常finally
:无论是否异常,最终执行try-except-else-finally
组合try:
# 尝试操作
file = open("config.json", "r")
except FileNotFoundError:
# 处理缺失配置
print("使用默认配置")
config = DEFAULT_CONFIG
else:
# 无异常时读取配置
try:
config = json.load(file)
except json.JSONDecodeError:
print("配置格式错误,使用默认值")
config = DEFAULT_CONFIG
finally:
file.close() # 确保文件关闭
finally:
# 应用配置
apply_config(config)
if os.path.exists(file)
)