准备工作:安装 requests 库
如果你的 Python 环境中还没有安装 requests,可以通过 pip 进行安装:

pip install requests
从服务器下载文件
这是最常见的用例之一,这里的“文件”可以是任何可以被服务器作为响应返回的内容,比如图片、PDF、CSV 文件、压缩包等。
核心方法:requests.get()
下载文件的关键在于正确处理响应对象 Response 的 content 属性。
response.content: 返回的是二进制数据(bytes),这是下载图片、视频、PDF 等二进制文件时必须使用的属性。response.text: 返回的是字符串(str),它已经经过了编码解码,适用于下载 HTML、TXT、JSON 等文本文件。
示例1:下载并保存一张图片(二进制文件)
假设我们要下载一张示例图片并保存到本地。
import requests
# 目标文件的 URL
url = "https://www.python.org/static/community_logos/python-logo-master-v3-TM.png"
# 1. 发送 GET 请求
try:
response = requests.get(url, stream=True) # stream=True 对于大文件非常重要
# 2. 检查请求是否成功 (状态码 200)
response.raise_for_status() # 如果请求失败 (404, 500), 会抛出异常
# 3. 获取文件名(从 URL 中提取)
filename = url.split("/")[-1]
# 4. 以二进制写入模式 ('wb') 保存文件
with open(filename, 'wb') as f:
# response.iter_content(chunk_size=8192) 可以分块读取内容,节省内存
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
print(f"文件 '{filename}' 下载成功!")
except requests.exceptions.RequestException as e:
print(f"下载失败: {e}")
代码解析:

stream=True: 这是一个非常重要的参数,尤其是在下载大文件时,它告诉requests不要立即下载整个响应体到内存,而是允许我们以流的方式逐步读取数据,这样可以避免内存耗尽。response.raise_for_status(): 这是一个好习惯,HTTP 请求返回了错误的状态码(如 404 Not Found, 500 Server Error),它会抛出一个HTTPError异常,帮助我们快速定位问题。response.iter_content(chunk_size=8192): 这是流式读取的核心,它会返回一个迭代器,每次生成一块数据(这里设置为 8KB),我们在一个循环中逐块写入文件,非常高效。with open(..., 'wb') as f: 使用with语句可以确保文件在操作完成后被自动关闭。'wb'表示以二进制写入模式打开文件。
示例2:下载并保存一个文本文件(如 CSV)
对于文本文件,我们可以使用 response.text。
import requests
url = "https://raw.githubusercontent.com/datasets/covid-19/main/data/time-series-19-covid-combined.csv"
try:
response = requests.get(url)
response.raise_for_status() # 检查请求是否成功
# 获取文件名
filename = url.split("/")[-1]
# 以文本写入模式 ('w') 保存文件
# 需要指定编码,通常是 utf-8
with open(filename, 'w', encoding='utf-8') as f:
f.write(response.text)
print(f"文件 '{filename}' 下载成功!")
except requests.exceptions.RequestException as e:
print(f"下载失败: {e}")
上传文件到服务器
上传文件通常使用 POST 或 PUT 请求。requests 让这个过程变得非常简单。
核心方法:requests.post()
你需要准备一个字典,files 参数是关键。files 参数的值是一个字典,键是服务器端期望的表单字段名,值是一个文件元组。
文件元组的格式为:(文件名, 文件对象, content_type)

文件名: 字符串,上传到服务器时显示的文件名。文件对象: 一个文件对象(通过open()以二进制读取模式'rb'打开)。content_type(可选): 文件的 MIME 类型,如image/jpeg。
示例:上传本地文件到服务器
假设有一个本地文件 my_report.pdf,我们要将它上传到一个支持文件上传的 API。
import requests
# 目标上传 URL (这里使用一个公共的测试 API)
url = "https://httpbin.org/post"
# 本地要上传的文件路径
file_path = "my_report.pdf" # 请确保这个文件存在
# 准备要上传的文件
# 'file' 是服务器端期望的字段名,请根据 API 文档修改
# ('my_report.pdf', open(file_path, 'rb'), 'application/pdf') 中的 'application/pdf' 是可选的
files = {
'file': (file_path, open(file_path, 'rb'))
}
# 其他表单数据 (可选)
data = {
'description': '这是我的月度报告'
}
try:
# 发送 POST 请求,包含文件和其他数据
response = requests.post(url, files=files, data=data)
response.raise_for_status() # 检查请求是否成功
# 打印服务器返回的响应
print("上传成功!服务器响应:")
print(response.json())
except requests.exceptions.RequestException as e:
print(f"上传失败: {e}")
finally:
# 确保文件被关闭
files['file'][1].close()
代码解析:
open(file_path, 'rb'): 我们必须以二进制读取模式 ('rb') 打开本地文件。files = {'file': ...}: 构建一个字典,键'file'是向服务器提交数据时使用的字段名,这个字段名需要根据目标服务器的 API 文档来确定。data参数: 如果除了文件本身,还需要提交其他表单数据(如描述、标签等),可以使用data参数。finally块: 这是一个很好的编程习惯,无论请求成功还是失败,finally块中的代码都会被执行,确保我们打开的文件被正确关闭,防止资源泄漏。
在内存中处理文件
有时候你并不想将文件保存到磁盘,而是想在内存中直接处理它(解析一个 CSV 文件或对图片进行一些操作)。
这非常简单,直接使用 response.content 或 response.text 即可。
示例:下载 CSV 并直接用 csv 模块解析
import requests
import csv
import io
url = "https://raw.githubusercontent.com/datasets/covid-19/main/data/time-series-19-covid-combined.csv"
try:
response = requests.get(url)
response.raise_for_status()
# response.content 是二进制数据,需要解码成字符串
# 使用 io.StringIO 将字符串包装成一个类似文件的对象
csv_file = io.StringIO(response.text.decode('utf-8'))
# 现在可以直接将 csv_file 传给 csv.reader
csv_reader = csv.reader(csv_file)
# 读取并打印前5行(不包括表头)
header = next(csv_reader) # 读取表头
print("表头:", header)
print("\n前5行数据:")
for i, row in enumerate(csv_reader):
if i < 5:
print(row)
else:
break
except requests.exceptions.RequestException as e:
print(f"下载或解析失败: {e}")
代码解析:
response.text: 获取文件内容为字符串。io.StringIO(): 这是一个非常有用的工具,它创建了一个在内存中的文本缓冲区,可以像操作文件一样操作这个字符串(传递给csv.reader)。- 对于二进制文件(如图片),可以使用
io.BytesIO(response.content)来创建一个内存中的二进制文件对象。
总结与最佳实践
| 场景 | 方法 | 关键点 |
|---|---|---|
| 下载二进制文件 (图片, PDF, 视频) | requests.get(url, stream=True)with open(filename, 'wb') as f:for chunk in response.iter_content():f.write(chunk) |
必须使用 stream=True 和 response.iter_content(),避免内存问题,写入模式为 'wb'。 |
| 下载文本文件 (HTML, CSV, TXT) | requests.get(url)with open(filename, 'w', encoding='utf-8') as f:f.write(response.text) |
使用 response.text,写入模式为 'w',并指定正确的 encoding。 |
| 上传文件 | requests.post(url, files={'key': (filename, file_obj)}) |
本地文件需以 'rb' 模式打开。files 字典的键需符合 API 要求。 |
| 在内存中处理文件 | data = response.content (二进制) 或 data = response.text (文本) |
使用 io.StringIO 或 io.BytesIO 将数据包装成文件对象,以便传给其他库(如 csv, PIL)。 |
| 通用实践 | 使用 try...except 处理网络错误。使用 response.raise_for_status() 检查 HTTP 错误。使用 with open(...) 或 finally 确保资源被正确释放。 |
写健壮、可维护的代码。 |
希望这份详细的指南能帮助你熟练掌握 requests 库的文件操作!
