基于 Oxlo.ai API 构建 Python 代码审查 CLI 的教程,可对遗留脚本进行 bug、安全风险和重构候选识别,返回结构化 JSON 报告。
我需要一种快速的方式来审计遗留 Python 脚本,排查明显的 bug 和反模式,又不想搭建一套完整的静态分析流程。在本指南中,我将带你实现一个小型 CLI 工具,它将源文件发送给 LLM 并返回结构化的 JSON 问题报告,基于 Oxlo.ai 构建,因此长文件不会推高成本。
前置条件:
OpenAI SDK:pip install openai
一个 Oxlo.ai API Key,地址:https://portal.oxlo.ai
创建 analyzer.py 并初始化 Oxlo.ai 客户端。Oxlo.ai 完全兼容 OpenAI SDK,所以只需要修改 base URL。
from openai import OpenAI
import json
import sys
from pathlib import Path
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key="YOUR_OXLO_API_KEY" # get yours at https://portal.oxlo.ai
)
这个 prompt 强制模型只输出 JSON,并定义了我们关心的三个类别:bug、安全风险和重构候选。
SYSTEM_PROMPT = '''You are a senior code reviewer. Analyze the provided code and return a single JSON object with exactly these keys:
- "bugs": a list of objects, each with "line" (int), "severity" ("low"|"medium"|"high"), and "description" (string).
- "security": a list of objects with the same schema.
- "refactors": a list of objects with the same schema.
Do not include markdown fences, explanations, or any text outside the JSON object.'''
我们读取文件并构建用户消息。我让消息尽可能精简,让模型专注于代码本身。
def load_code(path: str) -> str:
return Path(path).read_text(encoding="utf-8")
def build_user_message(code: str, filename: str) -> str:
return f"Filename: {filename}\n\n```python\n{code}\n```\n\nReturn the JSON review."
我使用 Llama 3.3 70B,因为它能可靠地处理长上下文。如果需要对复杂算法进行更深入的推理,可以将模型换成 qwen-3-32b 或 deepseek-v3.2,而无需修改其他代码。由于 Oxlo.ai 按请求次数计费而非按 token 计费,分析一个 400 行的模块和 10 行代码片段的费用相同。当前计费层级见 https://oxlo.ai/pricing。
def analyze_file(path: str):
code = load_code(path)
user_message = build_user_message(code, Path(path).name)
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
response_format={"type": "json_object"},
temperature=0.2,
)
raw = response.choices[0].message.content
return json.loads(raw)
添加一个小型 main 块来美化输出格式。
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python analyzer.py <file.py>")
sys.exit(1)
target = sys.argv[1]
result = analyze_file(target)
for category in ["bugs", "security", "refactors"]:
items = result.get(category, [])
print(f"\n{category.upper()} ({len(items)})")
for item in items:
line = item.get("line", "?")
severity = item.get("severity", "?")
desc = item.get("description", "No description")
print(f" Line {line} [{severity}] {desc}")
创建一个名为 test_script.py 的文件,加入一些刻意的问题。
import os
def fetch_data(user_input):
query = "SELECT * FROM users WHERE name = '" + user_input + "'"
os.system("echo " + user_input)
return query
unused_var = 42
现在运行分析器。
$ python analyzer.py test_script.py
BUGS (1)
Line 4 [medium] String concatenation into SQL query without parameterization
SECURITY (2)
Line 5 [high] Command injection risk via os.system with unsanitized user input
Line 4 [high] SQL injection vulnerability from raw string concatenation
REFACTORS (1)
Line 8 [low] Unused variable unused_var adds noise and should be removed
将 JSON 输出接入 CI 流水线,让每个 Pull Request 都获得一条自动评论。或者扩展脚本,使其遍历整个目录并将发现的问题聚合为一份 SARIF 报告,供 GitHub Advanced Security 使用。