python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python数据处理与API

Python数据处理与API实战指南

作者:蓝胖的四次元口袋

Python在数据处理和API调用方面极其简洁,这是它相比Java的一大优势——几行代码就能完成Java里需要十几行的工作,本文从JSON处理到HTTP请求,再到大模型API调用和FastAPI框架,覆盖秋招面试中最常见的实战技能,需要的朋友可以参考下

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
# }

参数说明:

// 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类型对照表:

JSONPythonJava
{} 对象dictMap / POJO
[] 数组listList
"string"strString
123intint/Integer
1.5floatdouble
true/falseTrue/Falseboolean
nullNonenull

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)

关键区别:

// 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}")

面试注意点:

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用户的提问客户的问题
assistantAI的回复(历史对话)员工之前的回答
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

面试常问:

剥洋葱取内容

大模型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());
    }
}

关键区别:

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 的使用场景

写在最后

学习建议

  1. requests库要烂熟于心:这是Python开发最常用的库,GET/POST/异常处理必须熟练。类比Java的OkHttp,但简洁10倍
  2. JSON处理记住dumps/loads:s=string,loads=load string,dump/load用于文件
  3. 大模型调用是加分项:秋招项目中如果涉及AI,能手写API调用代码会很加分。重点理解temperature参数和消息结构
  4. FastAPI了解即可:面试不要求精通,但知道装饰器路由、自动JSON转换、Pydantic验证这些概念,能体现技术广度

Java转Python的适应清单

Java习惯Python对应
Jackson/Gson序列化json.dumps() / json.loads()
OkHttp/HttpClientrequests.get() / requests.post()
DTO/VO实体类Pydantic的 BaseModel
@RestControllerFastAPI的 app = FastAPI()
@GetMapping@app.get()
@PathVariable函数参数自动匹配
application/jsonjson= 参数自动处理
Swagger配置FastAPI自动生成 /docs

以上就是Python数据处理与API实战指南的详细内容,更多关于Python数据处理与API的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文