今天用 OpenCode 写一个命令行随机密码生成器。输入一条指令,就能按指定长度、字符集生成高强度的随机密码,支持批量生成和密码强度评估。
secrets、argparse、string最终效果:
$ python pwdgen.py -l 20 -n 3 Xq7#mKp2@vR9&yLw3!sN jT5$hF8=cW3^nVb6@zQ1 Gd9%rE2*Px4~mA7#kL0 $ python pwdgen.py -l 16 --no-symbols 密码: aB3kQ9xR2mN5vF7w 熵值: 95.2 bits
直接告诉 OpenCode 要做什么:
> 我对 OpenCode 说:
> "用 Python 写一个命令行密码生成器,使用 argparse 解析参数,接受 --length 和 --count 两个选项,用 secrets 模块生成安全随机密码。保存到 pwdgen.py。"
OpenCode 会自动查找代码库中的 Python 文件了解项目风格,然后一次性生成完整代码:
import argparse
import secrets
import string
def generate_password(length=16):
chars = string.ascii_letters + string.digits + string.punctuation
return ''.join(secrets.choice(chars) for _ in range(length))
def main():
parser = argparse.ArgumentParser(description="安全密码生成器")
parser.add_argument("-l", "--length", type=int, default=16)
parser.add_argument("-n", "--count", type=int, default=1)
args = parser.parse_args()
for _ in range(args.count):
print(generate_password(args.length))
if __name__ == "__main__":
main()
关键要点:OpenCode 自动选择 secrets.choice 而非 random.choice——因为 secrets 模块是密码学安全的,适合生成密码。这说明它理解场景语义。
基础版本生成后,我希望增加更细粒度的控制——可以排除大写字母、数字或符号:
> 我对 OpenCode 说:
> "给 generate_password 增加三个布尔参数:upper、digits、symbols,默认全为 True。添加对应的命令行选项 --no-upper、--no-digits、--no-symbols。"
OpenCode 理解了这个需求,准确定位到 generate_password 函数和 argparse 部分,同时做了修改:
def generate_password(length=16, upper=True, digits=True, symbols=True):
chars = string.ascii_lowercase
if upper:
chars += string.ascii_uppercase
if digits:
chars += string.digits
if symbols:
chars += "!@#$%^&*()-_=+[]{}|;:,.<>?"
return ''.join(secrets.choice(chars) for _ in range(length))
为什么把 string.punctuation 换成自定义符号集?因为 string.punctuation 包含反斜杠和引号,在 Shell 中容易引起转义问题。OpenCode 在这个细节上表现出了工程意识。
继续迭代,加上"排除歧义字符"和"密码强度显示":
> 我对 OpenCode 说:
> "加一个 --no-ambiguous 选项,排除容易混淆的字符(0/O、1/l/I 等)。再增加密码熵值计算,每个密码后面显示熵值(bits),格式改成 '密码: xxx\n熵值: xx.x bits'。"
OpenCode 在已有代码上直接增补,不会打乱原有结构:
def entropy(password, chars):
import math
return len(password) * math.log2(len(set(chars)))
# 在 generate_password 中
if no_ambiguous:
ambiguous = "il1Lo0O"
chars = "".join(c for c in chars if c not in ambiguous)
关键要点:我并没有告诉 OpenCode 具体从哪些字符里排除,也没有说熵值公式怎么写——它根据"排除混淆字符""熵值计算"这些自然语言描述,自己推导出了实现方案。
最后再补一个安全下限和程序入口:
> 我对 OpenCode 说:
> "最短密码长度限制为 4,加一个 minimum check;补充 __main__ 入口,使用 argparse 解析参数并调用函数。"
OpenCode 把前面分散的逻辑整合成了一个完整的、可以独立运行的 CLI 程序。全程我没写一行代码,只是用自然语言描述需求。
#!/usr/bin/env python3
"""命令行随机密码生成器 —— 100% 标准库,零依赖。"""
import argparse
import math
import secrets
import string
import sys
def generate_password(length=16, upper=True, digits=True,
symbols=True, no_ambiguous=False):
"""生成一个安全随机密码。"""
chars = string.ascii_lowercase
if upper:
chars += string.ascii_uppercase
if digits:
chars += string.digits
if symbols:
chars += "!@#$%^&*()-_=+[]{}|;:,.<>?"
if no_ambiguous:
ambiguous = "il1Lo0O"
chars = "".join(c for c in chars if c not in ambiguous)
if not chars:
raise ValueError("没有可用的字符集")
return "".join(secrets.choice(chars) for _ in range(length))
def calc_entropy(password, chars):
"""计算密码熵值(bits)。"""
unique = len(set(chars))
return len(password) * math.log2(unique) if unique else 0
def main():
parser = argparse.ArgumentParser(
description="安全随机密码生成器",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="示例: python pwdgen.py -l 20 -n 5 --no-symbols",
)
parser.add_argument("-l", "--length", type=int, default=16,
help="密码长度(默认 16)")
parser.add_argument("-n", "--count", type=int, default=1,
help="生成数量(默认 1)")
parser.add_argument("--no-upper", action="store_true",
help="不含大写字母")
parser.add_argument("--no-digits", action="store_true",
help="不含数字")
parser.add_argument("--no-symbols", action="store_true",
help="不含特殊符号")
parser.add_argument("--no-ambiguous", action="store_true",
help="排除歧义字符 (il1Lo0O)")
args = parser.parse_args()
if args.length < 4:
print("错误:密码长度至少为 4", file=sys.stderr)
sys.exit(1)
chars = string.ascii_lowercase
if not args.no_upper:
chars += string.ascii_uppercase
if not args.no_digits:
chars += string.digits
if not args.no_symbols:
chars += "!@#$%^&*()-_=+[]{}|;:,.<>?"
if args.no_ambiguous:
ambiguous = "il1Lo0O"
chars = "".join(c for c in chars if c not in ambiguous)
for _ in range(args.count):
pwd = generate_password(
length=args.length,
upper=not args.no_upper,
digits=not args.no_digits,
symbols=not args.no_symbols,
no_ambiguous=args.no_ambiguous,
)
ent = calc_entropy(pwd, chars)
print(f"密码: {pwd}")
print(f"熵值: {ent:.1f} bits\n")
if __name__ == "__main__":
main()
# 默认生成 16 位密码,1 条 $ python pwdgen.py # 生成 5 条 20 位密码 $ python pwdgen.py -l 20 -n 5 # 纯字母数字,排除歧义字符 $ python pwdgen.py -l 12 --no-symbols --no-ambiguous
整个项目从零到完整可运行,花了大约 4 分钟。这 4 分钟里我没写一行代码,只是用自然语言告诉 OpenCode:
"帮我写一个密码生成器"
"加几个参数控制字符集"
"排除歧义字符,算一下强度"
"加长度校验和入口"
OpenCode 负责了所有的代码生成、语法细节、库选择和边界处理。我只需要关注"我想要什么",不用操心"怎么实现"。
相比传统写法——查文档、写骨架、调 bug、补边界——效率提升了至少 5 倍。更重要的是,这种"对话式编程"让你可以保持心流,想法→表达→出代码→迭代,整个过程像在和白板搭档结对编程。
如果你还没试过 OpenCode,打开终端,试着对它说出你的第一个需求。你会发现:写代码这件事,正在被重新定义。