🚀

用 Python + Ollama 做一个 AI 代码注释生成器,告别手写注释

选一段代码丢进去,AI 自动给你生成清晰准确的注释。支持 Python、JavaScript、Go、Java 等多种语言,注释风格可自定义,注释质量直接拉满。

👁️ - 次阅读

你有没有这种经历:翻出自己半年前写的代码,发现根本看不懂自己在干什么。

不是代码写得烂,而是注释太少。你觉得当时很简单,随手写了两行就过了。等回头再看,function 叫什么、参数传什么、为什么要这么写,全都搞不清楚了。

更常见的是,接手别人的代码,注释写得天花乱坠,但核心逻辑还是模糊。

今天做一个 AI 代码注释生成器。选一段代码丢进去,它自动分析逻辑,生成清晰准确的注释。全程本地跑,代码不上传,免费用。

项目背景

代码注释是开发者的老难题。写注释花 time,不写又难维护。人工写注释有几个痛点:

  • 懒得写,项目赶进度时直接跳过
  • 写了但不准确,反而误导读者
  • 风格不统一,有的用 docstring,有的用行注释
  • 改了代码忘改注释,注释和逻辑对不上

用 AI 做这件事,优势很明显:它不用你动笔,读完代码就能输出结构化注释。而且可以按你的要求调整风格——简洁版、详细版、行注释、块注释,全都行。

技术选型

组件选型理由
大模型Ollama + qwen2.5:7b中文注释理解强,本地免费
备选模型Ollama + llama3.2英文代码效果更好
语言检测根据文件扩展名判断简单直接,够用
交互方式终端 CLI零配置,直接跑
输入输出原文件 + 生成注释支持原地覆盖或另存

不需要 Web 框架,不需要数据库。纯 Python 脚本,跑在任意有 Ollama 的机器上。

实现步骤

第一步:安装 Ollama 和模型

# 安装 Ollama(如果还没装)
curl -fsSL https://ollama.com/install.sh | sh

# 拉取模型
ollama pull qwen2.5:7b

8GB 内存够用。代码注释任务不需要太大模型,7b 版本响应速度快,质量已经足够好。

第二步:安装 Python 依赖

pip install ollama

就一个包。

第三步:写注释生成器

新建 comment_generator.py:

#!/usr/bin/env python3
"""AI 代码注释生成器"""

import ollama
import sys
import os
from pathlib import Path


# 支持的语言和文件扩展名
LANGUAGE_MAP = {
    ".py": "Python",
    ".js": "JavaScript",
    ".ts": "TypeScript",
    ".jsx": "JavaScript",
    ".tsx": "TypeScript",
    ".go": "Go",
    ".java": "Java",
    ".c": "C",
    ".cpp": "C++",
    ".cs": "C#",
    ".rs": "Rust",
    ".php": "PHP",
    ".rb": "Ruby",
    ".swift": "Swift",
    ".kt": "Kotlin",
}

# 注释风格模板
STYLE_TEMPLATES = {
    "concise": "简洁版:每个函数只写一行说明,重点写清做什么、返回什么。",
    "detailed": "详细版:每个函数写完整 docstring,包含参数说明、返回值、异常说明、使用示例。",
    "inline": "行注释版:在每行关键代码旁边写注释,解释为什么这么写。",
}


def detect_language(filepath: str) -> str:
    """根据文件扩展名检测编程语言"""
    ext = Path(filepath).suffix.lower()
    return LANGUAGE_MAP.get(ext, "Unknown")


def read_code(filepath: str) -> str:
    """读取代码文件内容"""
    with open(filepath, "r", encoding="utf-8") as f:
        return f.read()


def generate_comments(code: str, language: str, style: str) -> str:
    """调用 Ollama 生成注释"""
    
    style_desc = STYLE_TEMPLATES.get(style, style)
    
    prompt = f"""你是一个专业的代码注释生成助手。你的任务是为给定的代码生成高质量的注释。

代码语言:{language}
注释风格:{style_desc}

要求:
1. 注释必须准确反映代码的实际逻辑
2. 对于函数/方法,说明其用途、参数含义和返回值
3. 对于复杂逻辑,解释为什么这样做
4. 不要添加冗余注释,每行注释都要有价值
5. 保持原有代码结构不变,只在适当位置插入注释
6. 用中文写注释

请直接输出添加了注释的完整代码,不要解释其他内容。

代码:
```{language.lower() if language != "Unknown" else "text"}
{code}

"""

response = ollama.chat(
    model="qwen2.5:7b",
    messages=[{"role": "user", "content": prompt}]
)
return response["message"]["content"]

def main(): if len(sys.argv) < 2: print(“用法: python comment_generator.py <代码文件路径> [风格]”) print("") print(“风格选项:”) print(" concise - 简洁版(默认)") print(" detailed - 详细版") print(" inline - 行注释版") print("") print(“示例:”) print(" python comment_generator.py my_script.py") print(" python comment_generator.py my_script.py detailed") print(" python comment_generator.py src/main.go inline") sys.exit(1)

filepath = sys.argv[1]
style = sys.argv[2] if len(sys.argv) > 2 else "concise"

# 检查文件
if not os.path.exists(filepath):
    print(f"❌ 文件不存在: {filepath}")
    sys.exit(1)

# 检测语言
language = detect_language(filepath)
if language == "Unknown":
    print(f"⚠️ 未识别的文件类型: {filepath},将作为通用代码处理")
    language = "通用代码"

print(f"📄 文件: {filepath}")
print(f"🔤 语言: {language}")
print(f"📝 风格: {style}")
print(f"🤖 正在分析代码,生成注释...")

# 读取代码
code = read_code(filepath)

# 生成注释
try:
    commented_code = generate_comments(code, language, style)
except Exception as e:
    print(f"❌ 生成失败: {e}")
    print("请确认 Ollama 正在运行: ollama list")
    sys.exit(1)

# 保存结果
original_path = Path(filepath)
style_suffix = f"_{style}" if style != "concise" else ""
output_path = original_path.parent / f"{original_path.stem}{style_suffix}_commented{original_path.suffix}"

with open(output_path, "w", encoding="utf-8") as f:
    f.write(commented_code)

print(f"✅ 注释已生成,保存到: {output_path}")
print(f"💡 对比方法:diff {filepath} {output_path}")

if name == “main”: main()


### 第四步:准备待注释的代码

随便写一段代码,保存为 `example.py`:

```python
def find_max_min(arr):
    if not arr:
        return None, None
    max_val = arr[0]
    min_val = arr[0]
    for i in range(1, len(arr)):
        if arr[i] > max_val:
            max_val = arr[i]
        elif arr[i] < min_val:
            min_val = arr[i]
    return max_val, min_val

def merge_sorted_arrays(a, b):
    result = []
    i = j = 0
    while i < len(a) and j < len(b):
        if a[i] <= b[j]:
            result.append(a[i])
            i += 1
        else:
            result.append(b[j])
            j += 1
    result.extend(a[i:])
    result.extend(b[j:])
    return result

class Stack:
    def __init__(self):
        self.items = []
    
    def push(self, item):
        self.items.append(item)
    
    def pop(self):
        if self.is_empty():
            return None
        return self.items.pop()
    
    def is_empty(self):
        return len(self.items) == 0
    
    def size(self):
        return len(self.items)

第五步:运行注释生成器

# 简洁版(默认)
python comment_generator.py example.py

# 详细版
python comment_generator.py example.py detailed

# 行注释版
python comment_generator.py example.py inline

运行后会自动生成 example_converted_commented.py 等文件。

第六步:对比效果

# 用 diff 对比原文件和注释后的文件
diff example.py example_converted_commented.py

# 或者用 meld 做可视化对比
meld example.py example_converted_commented.py

运行效果

以 example.py 为例,运行后生成的注释代码效果如下:

# 简洁版输出示例:

def find_max_min(arr):
    """返回数组中的最大值和最小值,使用一次遍历,时间复杂度 O(n)"""
    if not arr:
        return None, None
    max_val = arr[0]
    min_val = arr[0]
    for i in range(1, len(arr)):
        if arr[i] > max_val:
            max_val = arr[i]
        elif arr[i] < min_val:
            min_val = arr[i]
    return max_val, min_val

def merge_sorted_arrays(a, b):
    """合并两个已排序数组,保持有序性,时间复杂度 O(len(a) + len(b))"""
    result = []
    i = j = 0
    while i < len(a) and j < len(b):
        if a[i] <= b[j]:
            result.append(a[i])
            i += 1
        else:
            result.append(b[j])
            j += 1
    result.extend(a[i:])
    result.extend(b[j:])
    return result

class Stack:
    """基于列表实现的栈数据结构"""
    def __init__(self):
        """初始化空栈"""
        self.items = []
    
    def push(self, item):
        """将元素压入栈顶"""
        self.items.append(item)
    
    def pop(self):
        """弹出并返回栈顶元素,栈为空时返回 None"""
        if self.is_empty():
            return None
        return self.items.pop()
    
    def is_empty(self):
        """判断栈是否为空"""
        return len(self.items) == 0
    
    def size(self):
        """返回栈中元素个数"""
        return len(self.items)

详细版会在每个函数前生成包含参数说明、返回值、异常说明的完整 docstring。

优化方向

脚本跑通之后,还可以继续扩展:

  1. 批量处理:扫描整个项目目录,对所有代码文件批量生成注释,适合重构老项目。

  2. 增量更新:记录上次生成注释的时间,只处理新增或修改过的函数,节省 API 调用。

  3. 风格记忆:把人工修改过的注释存下来,下次生成时参考,让 AI 逐渐学习你的注释习惯。

  4. 多模型对比:同时用 qwen2.5 和 llama3.2 生成,对比两个版本,选注释质量更好的。

  5. 集成到 IDE:写成 VS Code 插件,选中代码按快捷键就能生成注释,开发流程无缝衔接。

  6. 质量评分:生成注释后,让 AI 对自己的注释打分,低于阈值的自动重新生成。

核心思路很简单:好的注释不是写出来的,是理解代码后自然生成的。AI 擅长理解代码,你只需要告诉它想要什么风格的注释。

你的项目里有没有注释太少、想补又懒得补的代码?把它丢进去跑一圈看看效果。

这篇文章对你有帮助吗?