Python数据处理与API实战指南
作者:蓝胖的四次元口袋
Python在数据处理和API调用方面极其简洁,这是它相比Java的一大优势——几行代码就能完成Java里需要十几行的工作。本文从JSON处理到HTTP请求,再到大模型API调用和FastAPI框架,覆盖秋招面试中最常见的实战技能。
核心掌握:json模块的序列化/反序列化、requests库的GET/POST用法、API调用四步法、大模型API调用(含temperature参数)、FastAPI基础用法。
一、JSON处理
1.1 Python字典就是JSON
在Python中,字典(dict)天然就是JSON的Python形态。这是理解JSON处理的关键——JSON在Python里就是字典。
# 这就是一个"JSON对象"的Python形态
user = {
"name": "蓝胖",
"age": 22,
"skills": ["Python", "Java", "SQL"],
"address": {
"city": "北京",
"zip": "100000"
}
}
# 访问方式和JSON的键值对一模一样
print(user["name"]) # "蓝胖"
print(user["skills"][0]) # "Python"
print(user["address"]["city"]) # "北京"
// Java对比:需要定义实体类或用Map
// 方式1:实体类(繁琐)
public class User {
private String name;
private int age;
private List<String> skills;
// getter/setter...
}
// 方式2:Map(不够直观)
Map<String, Object> user = new HashMap<>();
user.put("name", "蓝胖");
user.put("age", 22);
核心区别:Python的字典天然支持JSON结构,不需要定义实体类。Java需要Jackson/Gson做序列化,Python只需要 json 模块。
1.2 json.dumps —— 字典转JSON字符串
import json
user = {"name": "蓝胖", "age": 22}
# 字典 → JSON字符串(序列化)
json_str = json.dumps(user)
print(json_str) # {"name": "蓝胖", "age": 22}
# 格式化输出(缩进2空格,面试常用!)
json_pretty = json.dumps(user, indent=2, ensure_ascii=False)
print(json_pretty)
# {
# "name": "蓝胖",
# "age": 22
# }
参数说明:
indent=2:缩进2空格,便于阅读ensure_ascii=False:允许中文字符(默认True会把中文转成Unicode转义)
// Java对比(Jackson) ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(user); // 或 Gson String json = new Gson().toJson(user);
1.3 json.loads —— JSON字符串转字典
import json
json_str = '{"name": "蓝胖", "age": 22, "active": true}'
# JSON字符串 → 字典(反序列化)
user = json.loads(json_str)
print(user["name"]) # "蓝胖"
print(user["active"]) # True(注意:JSON的true变成Python的True)
# 安全解析(键不存在时不会报错)
city = user.get("city", "未知") # "未知"
JSON与Python类型对照表:
| JSON | Python | Java |
|---|---|---|
{} 对象 | dict | Map / POJO |
[] 数组 | list | List |
"string" | str | String |
123 | int | int/Integer |
1.5 | float | double |
true/false | True/False | boolean |
null | None | null |
1.4 json.dump / json.load —— 文件操作
import json
data = {"name": "蓝胖", "age": 22}
# 写入JSON文件
with open("user.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# 读取JSON文件
with open("user.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
print(loaded["name"]) # "蓝胖"
// Java对比(Jackson读文件)
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(new File("user.json"), User.class);1.5 常见坑点
# 坑1:dumps和loads搞混
json.dumps({"key": "value"}) # dict → str(序列化)
json.loads('{"key": "value"}') # str → dict(反序列化)
# 记忆技巧:s = string,loads = load string
# 坑2:单引号不是合法JSON
json.loads("{'key': 'value'}") # ❌ 报错!JSON必须用双引号
json.loads('{"key": "value"}') # ✅ 正确
# 坑3:中文乱码
json.dumps({"name": "蓝胖"}) # {"name": "\u84dd\u80d6"} ← 乱码
json.dumps({"name": "蓝胖"}, ensure_ascii=False) # {"name": "蓝胖"} ← 正确
二、requests库 —— HTTP请求
2.1 为什么用requests
Python的requests库是HTTP客户端的事实标准,类比Java的OkHttp/HttpClient。但在Python中,它比Java的方案简洁一个数量级。
# 先安装 pip install requests
// Java对比:HttpClient 需要多行代码
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.header("Content-Type", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
String body = response.body();2.2 GET请求
import requests
# 最简单的GET请求
response = requests.get("https://api.example.com/users")
# 带查询参数
params = {"page": 1, "size": 10, "keyword": "Python"}
response = requests.get("https://api.example.com/users", params=params)
# 实际请求URL:https://api.example.com/users?page=1&size=10&keyword=Python
# 带请求头
headers = {
"Authorization": "Bearer token123",
"User-Agent": "MyApp/1.0"
}
response = requests.get("https://api.example.com/users", headers=headers)
// Java对比(OkHttp)
OkHttpClient client = new OkHttpClient();
HttpUrl url = HttpUrl.parse("https://api.example.com/users").newBuilder()
.addQueryParameter("page", "1")
.addQueryParameter("size", "10")
.build();
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", "Bearer token123")
.build();
Response response = client.newCall(request).execute();2.3 POST请求
import requests
# 发送JSON数据(最常用!)
payload = {
"name": "蓝胖",
"age": 22,
"skills": ["Python", "Java"]
}
headers = {"Content-Type": "application/json"}
response = requests.post("https://api.example.com/users", json=payload, headers=headers)
# 注意:json= 参数会自动设置 Content-Type 并序列化字典为JSON
# 所以上面的headers可以省略!
# 简化写法
response = requests.post("https://api.example.com/users", json=payload)
# 发送表单数据(类比 form-urlencoded)
form_data = {"username": "lanpang", "password": "123456"}
response = requests.post("https://api.example.com/login", data=form_data)
关键区别:
json=payload:自动序列化为JSON,自动设置Content-Type: application/jsondata=payload:作为表单数据发送(application/x-www-form-urlencoded)
// Java对比(OkHttp POST JSON)
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, new Gson().toJson(payload));
Request request = new Request.Builder()
.url("https://api.example.com/users")
.post(body)
.build();
Response response = client.newCall(request).execute();2.4 响应处理
response = requests.get("https://api.example.com/users")
# 状态码(类比 response.statusLine().statusCode())
print(response.status_code) # 200, 404, 500...
# 响应体
print(response.text) # 原始字符串
data = response.json() # 自动解析JSON为字典!(超级方便)
print(data["name"]) # 直接用
# 响应头
print(response.headers) # 所有响应头
print(response.headers["Content-Type"]) # 特定响应头
# 请求的URL(看最终请求地址)
print(response.url)
// Java对比 int code = response.code(); String body = response.body().string(); // Java需要手动解析JSON: JsonObject json = JsonParser.parseString(body).getAsJsonObject();
2.5 异常处理
import requests
try:
response = requests.get("https://api.example.com/data", timeout=5)
# 检查HTTP状态码,非2xx会抛出异常
response.raise_for_status()
# 处理数据
data = response.json()
except requests.exceptions.Timeout:
print("请求超时")
except requests.exceptions.ConnectionError:
print("连接失败")
except requests.exceptions.HTTPError as e:
print(f"HTTP错误:{e}")
except requests.exceptions.RequestException as e:
print(f"请求异常:{e}")
面试注意点:
response.raise_for_status()只在状态码为4xx/5xx时抛异常,2xx不抛requests.get()本身不会因为404/500抛异常,需要手动调用raise_for_status()- 一定要设置
timeout参数,避免请求永久挂起
2.6 Session(会话保持)
# 需要多次请求同一个站点时,使用Session复用连接
session = requests.Session()
session.headers.update({"Authorization": "Bearer token123"})
# 后续请求自动带上headers
resp1 = session.get("https://api.example.com/users")
resp2 = session.get("https://api.example.com/orders")
# 类比Java OkHttp的OkHttpClient复用
三、API调用实战
3.1 API调用四步法
无论调用什么API,都可以按这四步来:
1. 准备参数 → 2. 发送请求 → 3. 解析响应 → 4. 提取内容
3.2 天气API实战
import requests
import os
from dotenv import load_dotenv
load_dotenv()
def get_weather(city: str) -> dict:
"""查询天气信息"""
# 1. 准备参数
url = "https://api.weather.com/v1/current"
params = {"city": city, "key": os.getenv("WEATHER_API_KEY")}
headers = {"Accept": "application/json"}
# 2. 发送请求
response = requests.get(url, params=params, headers=headers, timeout=10)
# 3. 解析响应
response.raise_for_status()
data = response.json()
# 4. 提取内容
return {
"city": city,
"temperature": data["current"]["temp"],
"humidity": data["current"]["humidity"],
"description": data["current"]["weather_desc"]
}
# 使用
weather = get_weather("北京")
print(f"{weather['city']}:{weather['temperature']}°C,{weather['description']}")
3.3 Qwen大模型API调用(重点!)
这是秋招项目中最可能用到的——调用通义千问大模型API。
三种角色
大模型API有三种角色,类比一个对话场景:
| 角色 | 说明 | 类比 |
|---|---|---|
system | 系统提示词,设定AI的行为 | 给员工的工作手册 |
user | 用户的提问 | 客户的问题 |
assistant | AI的回复(历史对话) | 员工之前的回答 |
messages = [
{"role": "system", "content": "你是一个专业的Python老师,擅长用Java对比来讲解Python"},
{"role": "user", "content": "Python的列表和Java的ArrayList有什么区别?"},
{"role": "assistant", "content": "Python列表是动态类型的,可以混合存放不同类型的元素..."},
{"role": "user", "content": "能给个代码例子吗?"}
]
完整的API调用
import requests
import os
from dotenv import load_dotenv
load_dotenv()
def call_qwen(prompt: str, system_prompt: str = "你是一个有帮助的AI助手。") -> str:
"""调用通义千问大模型"""
# 1. 准备参数
url = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
headers = {
"Authorization": f"Bearer {os.getenv('DASHSCOPE_API_KEY')}",
"Content-Type": "application/json"
}
payload = {
"model": "qwen-turbo", # 模型选择
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": prompt}
],
"temperature": 0.7 # 创造性参数
}
# 2. 发送请求
response = requests.post(url, json=payload, headers=headers, timeout=30)
# 3. 解析响应
response.raise_for_status()
result = response.json()
# 4. 剥洋葱取内容
# 结构:result["choices"][0]["message"]["content"]
content = result["choices"][0]["message"]["content"]
return content
# 使用
answer = call_qwen("用Python写一个快速排序")
print(answer)
temperature参数 —— 创造性旋钮
temperature 控制模型输出的随机程度,取值范围0~2:
# temperature = 0:确定性输出,每次结果几乎一样
# 适合:代码生成、数据分析、事实查询
payload = {"model": "qwen-turbo", "messages": messages, "temperature": 0}
# temperature = 0.7:平衡模式(默认推荐)
# 适合:一般对话、内容创作
# temperature = 1.0+:创造性输出,结果更多样
# 适合:头脑风暴、创意写作、广告文案
payload = {"model": "qwen-turbo", "messages": messages, "temperature": 1.0}
// Java对比:没有直接对应的概念 // 类比:生成验证码时的随机种子 // temperature=0 像是用固定种子的Random,每次结果一致 // temperature=1 像是完全随机的Random
面试常问:
- 为什么temperature=0时结果更稳定?因为模型总是选择概率最高的token
- 什么场景用低temperature?代码生成、数学计算等需要确定性的场景
- 什么场景用高temperature?创意写作、广告文案等需要多样性的场景
剥洋葱取内容
大模型API的响应是多层嵌套的JSON,需要逐层提取:
# 响应结构
{
"id": "chatcmpl-xxx",
"model": "qwen-turbo",
"choices": [ # 可能有多个候选回复
{
"index": 0,
"message": { # 消息对象
"role": "assistant",
"content": "这是AI的回复" # ← 我们最终要拿的内容
},
"finish_reason": "stop"
}
],
"usage": { # token用量
"prompt_tokens": 50,
"completion_tokens": 100,
"total_tokens": 150
}
}
# 逐层提取(像剥洋葱一样)
content = response["choices"][0]["message"]["content"]
# 安全写法(防止键不存在)
content = response.get("choices", [{}])[0].get("message", {}).get("content", "")// Java对比(用Jackson解析同样的结构)
JsonNode root = mapper.readTree(responseBody);
String content = root.path("choices").path(0).path("message").path("content").asText();
// Java的path()方法也是类似的逐层访问,但更啰嗦3.4 多轮对话实现
def chat_with_qwen():
"""支持多轮对话的大模型交互"""
messages = [
{"role": "system", "content": "你是Python老师,用Java对比教学"}
]
while True:
user_input = input("你:")
if user_input.lower() in ["quit", "exit", "q"]:
break
# 把用户输入加入对话历史
messages.append({"role": "user", "content": user_input})
# 调用API
response = requests.post(
"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
headers={"Authorization": f"Bearer {os.getenv('DASHSCOPE_API_KEY')}"},
json={"model": "qwen-turbo", "messages": messages, "temperature": 0.7},
timeout=30
)
response.raise_for_status()
# 提取回复
reply = response.json()["choices"][0]["message"]["content"]
# 把AI回复也加入历史(实现上下文记忆)
messages.append({"role": "assistant", "content": reply})
print(f"AI:{reply}\n")
# chat_with_qwen()
四、FastAPI —— 构建API服务
4.1 FastAPI是什么
FastAPI是Python最流行的Web框架之一,用于快速构建API服务。类比Java的Spring Boot。
pip install fastapi uvicorn # uvicorn是ASGI服务器,类比Tomcat
4.2 第一个FastAPI应用
# main.py
from fastapi import FastAPI
app = FastAPI()
# 路由装饰器(类比 @GetMapping)
@app.get("/")
def root():
return {"message": "Hello World"} # return字典自动转JSON!
@app.get("/users/{user_id}")
def get_user(user_id: int): # 路径参数自动类型转换
return {"user_id": user_id, "name": "蓝胖"}
@app.get("/users")
def list_users(page: int = 1, size: int = 10): # 查询参数
return {"page": page, "size": size, "users": []}
// Java对比(Spring Boot)
@RestController
public class UserController {
@GetMapping("/")
public Map<String, String> root() {
return Map.of("message", "Hello World");
}
@GetMapping("/users/{user_id}")
public Map<String, Object> getUser(@PathVariable int userId) {
return Map.of("user_id", userId, "name", "蓝胖");
}
@GetMapping("/users")
public Map<String, Object> listUsers(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
return Map.of("page", page, "size", size, "users", List.of());
}
}关键区别:
- FastAPI:return字典 → 自动转JSON响应。Spring Boot:return对象 → Jackson自动序列化
- FastAPI:路径参数直接写函数参数。Spring Boot:需要
@PathVariable - FastAPI:查询参数通过默认值声明。Spring Boot:需要
@RequestParam
4.3 POST请求处理
from fastapi import FastAPI
from pydantic import BaseModel # 数据验证(类比Java的@Valid + DTO)
app = FastAPI()
# 定义数据模型(类比Java的DTO/VO)
class UserCreate(BaseModel):
name: str
age: int
skills: list[str] = [] # 可选字段,默认空列表
# POST路由(类比 @PostMapping)
@app.post("/users")
def create_user(user: UserCreate): # 自动解析JSON请求体
# user已经是UserCreate对象了!
return {
"id": 1,
"name": user.name,
"age": user.age,
"skills": user.skills
}
// Java对比
@PostMapping("/users")
public UserVO createUser(@RequestBody @Valid UserCreateDTO dto) {
UserVO vo = new UserVO();
vo.setId(1);
vo.setName(dto.getName());
vo.setAge(dto.getAge());
vo.setSkills(dto.getSkills());
return vo;
}FastAPI的优势:Pydantic的BaseModel比Java的DTO简洁太多。只需要定义字段和类型,自动完成JSON解析、数据验证、类型转换。
4.4 路径参数 vs 查询参数
# 路径参数:在URL路径中
@app.get("/users/{user_id}")
def get_user(user_id: int): # /users/123
return {"user_id": user_id}
# 查询参数:不在路径中的参数
@app.get("/users")
def list_users(page: int = 1, size: int = 10): # /users?page=1&size=10
return {"page": page, "size": size}
# 混合使用
@app.get("/users/{user_id}/orders")
def get_user_orders(user_id: int, status: str = "all"):
# /users/123/orders?status=pending
return {"user_id": user_id, "status": status}
// Java对比
@GetMapping("/users/{userId}")
public User getUser(@PathVariable Long userId,
@RequestParam(defaultValue = "all") String status) {
// ...
}4.5 运行FastAPI
# 启动开发服务器(类比 java -jar 或 mvn spring-boot:run) uvicorn main:app --reload --port 8000 # 参数说明: # main:app → main.py文件中的app对象 # --reload → 代码修改自动重载(开发模式) # --port 8000 → 端口号 # 访问: # http://localhost:8000 → 根路由 # http://localhost:8000/docs → 自动生成的API文档(Swagger UI) # http://localhost:8000/redoc → 另一种API文档
亮点:FastAPI自动生成Swagger文档,比Spring Boot的Swagger配置简单得多。启动后访问
/docs就能测试所有API。
五、常见坑点与面试题
坑点1:requests的json=和data=的区别
# json= → 发送JSON(Content-Type: application/json)
requests.post(url, json={"key": "value"})
# data= → 发送表单(Content-Type: application/x-www-form-urlencoded)
requests.post(url, data={"key": "value"})
# 面试常问:调大模型API用哪个?→ json=
坑点2:response.json() 不是字符串
response = requests.get("https://api.example.com/data")
data = response.json() # 这已经是dict了,不是字符串!
# ❌ 常见错误
data = response.json()
data_str = json.dumps(data) # 多此一举!
data_again = json.loads(data_str) # 更没必要!
# ✅ 直接用
name = data["name"]
坑点3:FastAPI的async不是一定要写
# 同步写法(简单场景足够)
@app.get("/data")
def get_data():
return {"result": "ok"}
# 异步写法(需要await其他异步操作时)
@app.get("/data")
async def get_data():
result = await some_async_function()
return {"result": result}
# 注意:如果函数内部没有await,不要用async def
# 否则可能阻塞事件循环
面试题
Q:json.dumps和json.loads的区别?
json.dumps() 将Python字典序列化为JSON字符串(dict→str),json.loads() 将JSON字符串反序列化为Python字典(str→dict)。记忆技巧:s代表string,loads就是"load from string"。
Q:requests库的GET和POST有什么区别?
GET用 requests.get(url, params={}) ,参数拼接到URL上;POST用 requests.post(url, json={}) 或 data={},参数放在请求体中。json= 发送JSON格式,data= 发送表单格式。
Q:大模型API中temperature参数的作用?
temperature控制模型输出的随机性。0表示确定性输出,每次结果几乎相同,适合代码生成等场景;1.0表示高创造性,结果更加多样,适合创意写作。0.7是常用的平衡值。
Q:FastAPI的装饰器和Spring Boot的注解有什么关系?
FastAPI的 @app.get("/path") 等同于Spring Boot的 @GetMapping("/path"),都是路由映射。FastAPI通过函数参数自动识别路径参数和查询参数,Spring Boot需要显式标注 @PathVariable 和 @RequestParam。FastAPI return字典自动转JSON,Spring Boot return对象由Jackson序列化。
Q:如何在Python中安全地管理API密钥?
使用 .env 文件存储密钥,通过 python-dotenv 的 load_dotenv() 加载到环境变量,代码中用 os.getenv("API_KEY") 读取。.env 文件加入 .gitignore 不提交到版本控制。生产环境通过系统环境变量或配置中心注入。
思维导图速览
Python数据处理与API实战
├── JSON处理
│ ├── json.dumps():dict → JSON字符串(序列化)
│ ├── json.loads():JSON字符串 → dict(反序列化)
│ ├── json.dump() / json.load():文件读写
│ ├── 字典就是JSON的Python形态
│ └── 对比Java的Jackson/Gson
├── requests库
│ ├── GET:requests.get(url, params={}, headers={})
│ ├── POST:requests.post(url, json={}, headers={})
│ ├── 响应:status_code / text / json() / headers
│ ├── 异常:raise_for_status() + try/except
│ ├── Session:复用连接
│ └── 对比Java的HttpClient/OkHttp
├── API调用实战
│ ├── 四步法:准备参数→发送请求→解析响应→提取内容
│ ├── 天气API示例
│ ├── Qwen大模型调用
│ │ ├── 三种角色:system / user / assistant
│ │ ├── payload结构:model / messages / temperature
│ │ ├── temperature:0=确定性,1=创造性
│ │ └── 剥洋葱:response["choices"][0]["message"]["content"]
│ └── 多轮对话:维护messages列表
├── FastAPI
│ ├── @app.get / @app.post(类比@GetMapping / @PostMapping)
│ ├── return字典自动转JSON
│ ├── 路径参数:{param} + 函数参数
│ ├── 查询参数:带默认值的函数参数
│ ├── Pydantic BaseModel:请求体自动解析验证
│ └── 自动API文档:/docs(Swagger UI)
└── 常见坑点
├── json= vs data=
├── response.json()已经是dict
└── async def 的使用场景
写在最后
学习建议
- requests库要烂熟于心:这是Python开发最常用的库,GET/POST/异常处理必须熟练。类比Java的OkHttp,但简洁10倍
- JSON处理记住dumps/loads:s=string,loads=load string,dump/load用于文件
- 大模型调用是加分项:秋招项目中如果涉及AI,能手写API调用代码会很加分。重点理解temperature参数和消息结构
- FastAPI了解即可:面试不要求精通,但知道装饰器路由、自动JSON转换、Pydantic验证这些概念,能体现技术广度
Java转Python的适应清单
| Java习惯 | Python对应 |
|---|---|
| Jackson/Gson序列化 | json.dumps() / json.loads() |
| OkHttp/HttpClient | requests.get() / requests.post() |
| DTO/VO实体类 | Pydantic的 BaseModel |
@RestController | FastAPI的 app = FastAPI() |
@GetMapping | @app.get() |
@PathVariable | 函数参数自动匹配 |
application/json | json= 参数自动处理 |
| Swagger配置 | FastAPI自动生成 /docs |
以上就是Python数据处理与API实战指南的详细内容,更多关于Python数据处理与API的资料请关注脚本之家其它相关文章!
