OpenCode 实践课:4 分钟用 Python 写出一个命令行随机数据生成器

项目介绍

日常开发中,我们经常需要测试数据来填充列表、验证分页、跑性能测试。与其手动编造或网上找假数据,不如自己写一个命令行工具。

本文将展示如何用 OpenCode 在 4 分钟内完成一个命令行随机数据生成器,支持生成中文姓名、年龄、手机号、邮箱、地址等字段,输出 JSON 或 CSV 格式。技术栈:Python 3 + 标准库,零外部依赖。

准备工作

在终端中进入工作目录,启动 OpenCode:

mkdir mockgen && cd mockgen
opencode

实践过程

第一步:搭建基本框架

我对 OpenCode 说:

> "帮我写一个 Python 命令行工具,用 argparse 解析 -n 参数控制生成条数,每条数据包含随机生成的中文姓名。"

OpenCode 快速生成了骨架代码——导入 argparse 和 random,定义了中文姓氏和名字列表,编写了随机姓名生成函数,并用 for 循环输出指定数量的姓名。

要点:提示词不需要写成规格说明书。像跟同事聊天一样描述需求,说清楚"做什么"即可,OpenCode 会补全"怎么做"。

第二步:丰富数据字段

框架跑通后,我继续补充:

> "每条记录再加上 age(18-60 的随机整数)、phone(中国大陆手机号格式)、email(姓名+数字 @ 常见域名)。"

OpenCode 在已有代码上添加了三个生成函数:

def random_phone():
    prefix = random.choice(["13", "15", "18"]) + str(random.randint(0, 9))
    suffix = ''.join(random.choices(string.digits, k=9))
    return prefix + suffix

def random_email(name):
    return name + str(random.randint(100, 999)) + '@' + random.choice(DOMAINS)

要点:分步骤迭代是最佳策略。每次让 OpenCode 聚焦一个小模块,代码质量更高,验证也更方便。避免一次性描述全部需求——信息量过大时 AI 反而容易遗漏细节。

第三步:支持 JSON 和 CSV 输出

我对 OpenCode 说:

> "加上 -f 参数控制输出格式,支持 json 和 csv。json 要 indent=2 美化,csv 第一行是表头。"

OpenCode 添加了 -f 参数、to_csv() 格式化函数和条件分支。生成的数据先存入列表,再根据格式参数统一输出。

要点:指定输出格式时给出具体参数(如 indent=2),能帮 OpenCode 生成更准确的代码。模糊的描述会让 AI 猜测,正确率会下降。

第四步:收尾打磨

最后两句补充:

> "加个 --seed 参数支持随机种子,方便复现数据。再加 address 和 job 两个字段,以及 --fields 参数按需选择输出字段。"

OpenCode 加上了 random.seed()、地址生成逻辑、职业列表和 --fields 过滤器。代码定型。

测试一下:

python mockgen.py -n 3 -f csv --fields name age phone

输出:

name,age,phone
赵敏,28,18765432109
李伟,35,15210987654
钱磊,22,13012348765

完整代码

#!/usr/bin/env python3
import argparse
import json
import random
import string

SURNAMES = ["赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈",
            "杨", "朱", "黄", "刘", "林", "张", "何", "胡", "徐", "马"]

MALE_NAMES = ["伟", "强", "磊", "涛", "明", "超", "华", "军", "勇", "建国"]
FEMALE_NAMES = ["芳", "敏", "静", "丽", "婷", "雪", "玲", "英", "玉兰", "桂英"]

PROVINCES = ["北京", "上海", "广东", "浙江", "江苏", "湖北", "四川", "陕西", "福建", "湖南"]
CITIES = {
    "北京": ["朝阳区", "海淀区", "丰台区"],
    "上海": ["浦东新区", "静安区", "徐汇区"],
    "广东": ["广州", "深圳", "东莞"],
    "浙江": ["杭州", "宁波", "温州"],
    "江苏": ["南京", "苏州", "无锡"],
    "湖北": ["武汉", "宜昌", "襄阳"],
    "四川": ["成都", "绵阳", "德阳"],
    "陕西": ["西安", "咸阳", "宝鸡"],
    "福建": ["福州", "厦门", "泉州"],
    "湖南": ["长沙", "株洲", "湘潭"],
}
STREETS = ["中山路", "解放路", "人民路", "和平路", "建设路"]
DOMAINS = ["qq.com", "163.com", "gmail.com", "outlook.com", "icloud.com"]
JOBS = ["工程师", "设计师", "产品经理", "运营", "教师", "医生", "销售", "会计"]

FIELDS = ["name", "age", "phone", "email", "address", "job"]


def random_name():
    surname = random.choice(SURNAMES)
    given = random.choice(MALE_NAMES + FEMALE_NAMES)
    return surname + given


def random_phone():
    prefix = random.choice(["13", "15", "18"]) + str(random.randint(0, 9))
    suffix = ''.join(random.choices(string.digits, k=9))
    return prefix + suffix


def random_email(name):
    return name + str(random.randint(100, 999)) + '@' + random.choice(DOMAINS)


def random_age():
    return random.randint(18, 60)


def random_address():
    province = random.choice(PROVINCES)
    city = random.choice(CITIES[province])
    street = random.choice(STREETS)
    number = random.randint(1, 500)
    return province + city + street + str(number) + "号"


def random_job():
    return random.choice(JOBS)


def generate_record(fields):
    name = random_name()
    record = {}
    if "name" in fields:
        record["name"] = name
    if "age" in fields:
        record["age"] = random_age()
    if "phone" in fields:
        record["phone"] = random_phone()
    if "email" in fields:
        record["email"] = random_email(name)
    if "address" in fields:
        record["address"] = random_address()
    if "job" in fields:
        record["job"] = random_job()
    return record


def to_csv(records):
    if not records:
        return ""
    headers = list(records[0].keys())
    lines = [",".join(headers)]
    for r in records:
        lines.append(",".join(str(r.get(h, "")) for h in headers))
    return "\n".join(lines)


def main():
    parser = argparse.ArgumentParser(
        description="命令行随机数据生成器 - 生成中文测试数据")
    parser.add_argument("-n", "--count", type=int, default=10, help="生成数据条数")
    parser.add_argument("-f", "--format", choices=["json", "csv"], default="json",
                        help="输出格式")
    parser.add_argument("-s", "--seed", type=int, default=None, help="随机种子")
    parser.add_argument("--fields", nargs="+", choices=FIELDS, default=FIELDS,
                        help="选择输出的字段")
    args = parser.parse_args()

    if args.seed is not None:
        random.seed(args.seed)

    records = [generate_record(args.fields) for _ in range(args.count)]

    if args.format == "csv":
        print(to_csv(records))
    else:
        print(json.dumps(records, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()

小结

用 OpenCode 完成这个 100 行的随机数据生成器,从想法到可运行工具大约花了 4 分钟。如果传统手写——查 random 模块文档、手写 CSV 拼接、调试 argparse——至少需要 15-20 分钟。

几点体会:

迭代式对话远优于一次性描述全部需求。分成 4 步,每步聚焦一个功能点,OpenCode 输出的代码质量明显更可靠。

给出具体示例(如数据格式、函数签名)能大幅提升准确度。模糊描述留给 AI 的猜测空间越大,返工概率越高。

小项目最适合 AI 辅助:代码量 100 行左右时,OpenCode 几乎可以一步到位,人工只需微调参数和验证结果。

下次需要测试数据时,跑一行命令即可:

python mockgen.py -n 100 -f csv > users.csv