news 2026/10/14 23:02:48

用Python和SQLite打造高效命令行待办事项应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Python和SQLite打造高效命令行待办事项应用

想做命令行待办事项应用的人,我猜你大概率不是冲着“没软件可用”来的。市面上的待办工具一抓一大把,网页端、手机端、桌面端,哪个不是开箱即用?之所以想自己动手,要么是嫌现成工具太重、太慢、数据不归自己管,要么就是想要一个完全贴合自己工作流的工具——可能只有几条命令,敲下去就能记、能查、能归档,不弹窗不推送不花哨。

这个需求听起来简单,真正落地的时候还是有不少门道。命令行待办事项应用,核心词有两个:“命令行”和“待办事项”。前者决定了交互形态,后者决定了数据模型。写一个能用的demo不难,但要做到自己天天愿意用、数据不丢、操作顺手、还能长期维护,就需要在架构、存储、解析、错误处理这些细节上多花心思。这篇文章我把整个构建过程拆开来讲,从方案选型、数据模型,到核心代码、踩坑记录,再到后续扩展方向,适合有一定编程基础、想把个人小工具做扎实的朋友参考。

1. 内容整体设计与思路拆解

1.1 为什么不是图形界面,而是命令行

图形界面有它的优势,可视化、点选方便,但对高频、短促的记录动作来说,命令行反而更高效。你可以想一下这个场景:正在写代码,脑子里突然冒出一个待办事项,手从键盘挪到鼠标,再去找新建按钮、填表单、点保存,这一套动作至少要5到10秒。如果是命令行工具,直接在终端敲一行命令就完成了——不需要离开键盘,不需要切换窗口,甚至可以配合快捷键一键呼出终端。

命令行还有一个隐藏优势:天然适合脚本化和自动化。待办事项数据一旦是纯文本或者规整的数据库记录,就可以轻松接入其他工具。比如用脚本统计一周完成率,用定时任务自动添加重复事项,或者把待办列表渲染成网页挂到个人面板上。这些都是图形界面应用比较难提供的灵活性。

但命令行不是没有缺点。最大的问题是“心智负担”——你得记住命令和参数。解决办法是让命令设计得足够直觉化。好的命令行工具不是把一堆选项甩给用户,而是让80%的日常操作可以用最简单的子命令完成,复杂功能收在进阶参数里。我在设计时定的原则是:高频操作打字最少,低频操作看帮助就能懂。

1.2 这个应用解决了什么问题

说白了,它解决的是“记录、追踪、回顾”三个问题。

记录:任何时候有事情要做,3秒内把它写下来。不需要打开任何软件,不需要新建一个卡片。这是最核心的诉求,如果记录这个动作太慢、太繁琐,人就不愿意用了,工具自然废弃。

追踪:待办不只是记下来,还得能知道哪些做了、哪些没做、哪些快到期了、哪些优先级高。所以工具需要有状态管理、截止日期、优先级这些字段,并且支持按条件过滤查看。

回顾:做完的事情需要有迹可循。所以每一件事不能删了就没,应该有个“归档”的概念,可以查历史,可以做统计。这一点很多人设计自己的小工具时会忽略,等用了一阵子想回看“这个月完成了哪些事”,才发现工具根本不支持,那就会很遗憾。

1.3 目标用户和使用场景

这个工具最适合两种人:一种是开发者,日常大量工作在终端里完成,希望待办事项也能融入终端工作流;另一种是喜欢自己掌控数据的效率爱好者,不希望待办记录散落在某个不知名服务器上,而是想放在自己机器里,用文本格式保存,随时可以处理。

典型场景包括:写代码时临时记一个 bug 修复任务;做研究时记录要读的论文;管理个人项目中的小里程碑;甚至日常生活的购物清单、行程安排。命令行工具没有平台束缚,Linux、macOS、Windows(配合终端环境)都能跑,这也是选择它而不选择某个专用App的理由之一。

2. 方案选型:语言、存储、交互方式怎么定

2.1 技术栈的选择逻辑

先确定语言。可选的有 Python、Go、Rust、Node.js,甚至可以用 Shell 脚本写。我的建议是:Python 最省事,标准库够用,无需编译,跨平台性好,处理文本和 JSON 都很方便。Go 和 Rust 适合想把工具编译成单一二进制文件分发给别人用的场景,但开发周期会长一些。Shell 脚本写简单的增删改查可以,一旦涉及日期解析、模糊匹配、复杂查询,代码会迅速失控。

我个人选了 Python,理由很实际:开发速度快,标准库里的sqlite3、json、argparse直接覆盖了核心需求,不用引入任何第三方依赖。这样工具在任何装有 Python 的环境里都能跑,部署成本为零。

然后是存储方案。对比了一圈:

方案优点缺点适用场景
纯文本文件(每行一条)最简单,肉眼可读,可 diff不支持复杂查询,并发写入有风险极简场景或配合 git 使用
JSON 文件结构化,Python 解析方便大数据量性能差,修改需整体重写千条以内的小型工具
SQLite支持 SQL 查询,事务安全,性能好需要了解 SQL 基础功能完整、数据量较大的工具

最终选了 SQLite。它的容错性比 JSON 强得多,不会因为一次写操作中断导致整个文件损坏,而且支持条件过滤、排序、统计,这些功能在 JSON 方案里全得手写代码实现。

2.2 项目结构与模块划分

项目结构从一开始就要清晰,不然后续加功能的时候就是在屎山上叠新屎。我推荐这种布局:

todo/ ├── cli.py # 命令行入口,负责解析参数和分发指令 ├── database.py # 数据访问层,封装所有 SQL 操作 ├── models.py # 数据模型定义,待办事项的字段和状态常量 ├── utils.py # 工具函数,日期解析、优先级转换等 ├── config.py # 配置管理,数据库路径、默认参数 └── tests/ # 单元测试目录

模块之间单向依赖:cli.py调database.py和models.py,database.py不关心命令行参数,只处理数据存取。这样设计的好处是,后续想加一个 TUI 界面或者 Web 接口,只需要换掉cli.py,数据层完全不用动。

2.3 交互命令怎么设计

命令设计是整个工具用户体感的核心。参考了主流工具的做法,我定了这么一套:

todo add -t "描述" -d 2025-03-10 -p high todo list [--status pending|done] [--sort due_date|priority] todo done <id> todo rm <id> todo edit <id> -t "新描述" todo stats

原则很简单:动词是行为,参数是细节。add是核心高频操作,必须最省字;list是日常查看,要支持灵活过滤;done和rm要简洁,不允许多余确认——命令行用户不喜欢被反复询问“你确定吗?”,真正的保护是通过rm前的 id 二次输入或者仅归档不物理删除来实现。

3. 数据模型设计与核心功能拆解

3.1 待办事项的字段设计

在动手写代码之前,先把数据模型想清楚,能避免 80% 的重构。一个待办事项,最少需要这些字段:

  • id:唯一标识,用自增整数即可
  • title:待办内容描述,必填
  • status:状态,pending / done / archived
  • priority:优先级,high / medium / low,默认 medium
  • due_date:截止日期,可选
  • created_at:创建时间,自动生成
  • completed_at:完成时间,可选,统计时用
  • tags:标签,方便分类筛选,可选

这里有三个设计取舍值得说。第一,状态为什么要三个而不是两个?因为有些事项虽然不做了,但你不想它消失,归档可以保留记录同时不干扰当前列表。第二,completed_at为什么单独存?没有它,你只能知道“做完了”,不知道“什么时候做完的”,做周报、月统计的时候就拿不出数据。第三,tags字段用逗号分隔存储还是单独建表?对个人工具来说,逗号分隔字符串足够,在线过滤时用LIKE查询也能接受,没必要搞多对多关系表。

3.2 数据库表结构

既然选 SQLite,建表 SQL 长这样:

CREATE TABLE IF NOT EXISTS todos ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', priority TEXT NOT NULL DEFAULT 'medium', due_date TEXT, created_at TEXT NOT NULL DEFAULT (datetime('now', 'localtime')), completed_at TEXT, tags TEXT DEFAULT '' ); CREATE INDEX IF NOT EXISTS idx_status ON todos(status); CREATE INDEX IF NOT EXISTS idx_due_date ON todos(due_date);

两个索引加上之后,按状态过滤和按日期排序的查询会快不少。对个人工具来说数据量撑死几千条,性能差别其实感知不到,但养成建索引的习惯对写更大系统有好处。

有一点要注意:due_date存的是文本而不是原生日期类型。这是 SQLite 的特性决定的,它没有专门的日期类型,存成YYYY-MM-DD格式的字符串可以直接按字典序比较,比存时间戳更直观,读出来就在 SQL 层完成了格式化,不需要再额外转换。

3.3 核心功能清单

功能设计要克制,切忌贪多。第一个版本我圈定了六个功能:

功能说明
添加支持标题、截止日期、优先级、标签
查看默认显示未完成事项,可按状态/优先级/标签过滤
完成标记为完成,记录完成时间
编辑修改标题、日期、优先级、标签
删除物理删除或归档
统计完成率、每日完成数量、未完成数量汇总

六个功能覆盖了“记录、追踪、回顾”三个核心诉求,其余的花哨功能一概不做。等基础跑通了再按需加,这是个人项目最稳妥的迭代路径。

4. 实操过程与核心环节实现

4.1 数据库封装层实现

数据库操作是地基,先写这块。封装原则是:对外暴露符合直觉的函数,内部处理 SQL 细节。

import sqlite3 from contextlib import contextmanager from models import Todo, PRIORITY_MAP, STATUS_MAP DB_PATH = "todos.db" @contextmanager def get_conn(): conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row try: yield conn conn.commit() except Exception: conn.rollback() raise finally: conn.close()

row_factory设置成sqlite3.Row之后,查询结果可以直接用列名访问,比数字索引清晰太多。contextmanager封装了事务逻辑,函数体内正常执行就提交,抛出异常就回滚,调用方不需要关心连接生命周期。

增删改查的典型实现:

def add_todo(title, due_date=None, priority="medium", tags=""): with get_conn() as conn: cursor = conn.execute( "INSERT INTO todos (title, due_date, priority, tags) VALUES (?, ?, ?, ?)", (title, due_date, priority, tags), ) return cursor.lastrowid def complete_todo(todo_id): with get_conn() as conn: conn.execute( "UPDATE todos SET status = 'done', completed_at = datetime('now', 'localtime') WHERE id = ?", (todo_id,), ) def list_todos(status="pending", tag=None): query = "SELECT * FROM todos WHERE status = ?" params = [status] if tag: query += " AND tags LIKE ?" params.append(f"%{tag}%") query += " ORDER BY priority_sort(due_date) ..." # 排序逻辑见下文 with get_conn() as conn: rows = conn.execute(query, params).fetchall() return [Todo(**dict(row)) for row in rows]

所有 SQL 参数一律使用?占位符,绝不拼接字符串。这既是防注入的基本功,也避免了引号和转义的麻烦。

4.2 日期解析的细节处理

日期是命令行工具最容易翻车的点。用户输入可能是2025-03-10、3/10、明天、周五,还有可能是完全不合法的内容。写一个宽容但不含糊的解析函数:

from datetime import datetime, date, timedelta def parse_date(raw): if not raw or raw.strip() == "": return None raw = raw.strip().lower() today = date.today() # 处理相对表达 relative_map = { "今天": today.isoformat(), "明天": (today + timedelta(days=1)).isoformat(), "后天": (today + timedelta(days=2)).isoformat(), } if raw in relative_map: return relative_map[raw] # 尝试多种格式 formats = [ "%Y-%m-%d", "%Y/%m/%d", "%y-%m-%d", "%m-%d", "%m/%d", "%Y.%m.%d", ] for fmt in formats: try: parsed = datetime.strptime(raw, fmt).date() # 处理只写了月-日的情况 if fmt in ("%m-%d", "%m/%d"): parsed = parsed.replace(year=today.year) return parsed.isoformat() except ValueError: continue raise ValueError(f"无法解析日期: {raw},支持格式如 2025-03-10 或 明天")

两个细节值得注意:一是“只写月日”的输入要自动补上当前年份,否则日期会变成 1900 年;二是对解析失败要明确抛错,不能在数据库里留下脏数据。用户输错了就告诉他错在哪,这是命令行工具的礼仪。

4.3 优先级与排序策略

优先级本质是一个三级枚举。存储上我用字符串high/medium/low,而不是数字,因为字符串在调试时可读性更好。需要比较大小的时候映射成权重:

PRIORITY_WEIGHT = {"low": 0, "medium": 1, "high": 2} def priority_order(): return "CASE priority WHEN 'high' THEN 2 WHEN 'medium' THEN 1 ELSE 0 END"

排序逻辑放在 SQL 里。

def list_todos(status="pending", sort="priority"): base = "SELECT * FROM todos WHERE status = ?" if sort == "priority": sql = base + f" ORDER BY {priority_order()} DESC, due_date ASC" elif sort == "due_date": sql = base + " ORDER BY due_date IS NULL ASC, due_date ASC, priority_order() DESC" # ...

due_date IS NULL ASC这个写法是为了把没有截止日期的事项排到有日期的事项后面,避免一堆NULL把有日期的顶到天上。这个细节用起来感受特别明显,没有它列表里的有日期事项会被无日期事项淹没。

4.4 命令行参数解析

Python 自带的argparse已经够用,不需要额外引第三方库。但有个小技巧:把子命令分发逻辑做成 dict 查表,而不是写一串 if-else:

import argparse def build_parser(): parser = argparse.ArgumentParser( prog="todo", description="一个基于命令行的待办事项应用", ) subparsers = parser.add_subparsers(dest="command", required=True) # add 子命令 add_parser = subparsers.add_parser("add", help="添加待办") add_parser.add_argument("-t", "--title", required=True, help="待办内容") add_parser.add_argument("-d", "--due", help="截止日期,如 2025-03-10") add_parser.add_argument("-p", "--priority", choices=["low", "medium", "high"], default="medium") add_parser.add_argument("--tags", default="", help="逗号分隔的标签") # list 子命令 list_parser = subparsers.add_parser("list", help="查看待办") list_parser.add_argument("-s", "--status", choices=["pending", "done", "archived"], default="pending") list_parser.add_argument("--sort", choices=["priority", "due_date"], default="priority") list_parser.add_argument("--tag", help="按标签过滤") # ... done, edit, rm, stats 类似 return parser def dispatch(args): handlers = { "add": handle_add, "list": handle_list, "done": handle_done, "rm": handle_rm, "edit": handle_edit, "stats": handle_stats, } handler = handlers[args.command] handler(args) def main(): parser = build_parser() args = parser.parse_args() dispatch(args)

argparse的add_subparsers天生适合子命令风格的工具。required=True保证用户必须输入子命令,避免裸跑程序时不知所措。

4.5 输出格式与可读性

终端输出的排版直接影响使用意愿。一个漆黑终端里糊成一团的列表是没人愿意看的。输出函数要处理对齐、截断、颜色三件事。

def format_todo(todo): status_mark = { "pending": "[ ]", "done": "[x]", "archived": "[-]", }[todo.status] # 优先级标签 priority_color = { "high": "\033[31m", # 红色 "medium": "\033[33m", # 黄色 "low": "\033[32m", # 绿色 }[todo.priority] due_str = f" ({todo.due_date})" if todo.due_date else "" return f"{todo.id:>4}. {status_mark} {priority_color}[{todo.priority}]\033[0m {todo.title}{due_str}"

细节说明:\033[31m这种 ANSI 转义序列在没有终端颜色支持的场景会显示成乱码,所以输出前要检测环境变量,Windows 下还要显式启用 ANSI。一个简单的兼容方案是设置环境变量os.environ.setdefault("PYTHONIOENCODING", "utf-8"),并在 Windows 上调用os.system("")启用 ANSI 支持。

输出对齐方面,id 用右对齐到4位,标题按终端宽度截断到 80 字符左右,超长部分加省略号。表格类信息(比如统计结果)用简单的字符串排版,不要轻易引第三方tabulate库,个人工具依赖越少越好。

4.6 配置文件与自定义路径

数据库文件默认放在当前目录不是个好主意。用户可能从不同目录执行命令,每次数据库路径不一致,数据就“丢了”。正确做法是:默认路径放在用户目录下,同时允许环境变量覆盖。

import os def get_db_path(): env_path = os.environ.get("TODO_DB_PATH") if env_path: return env_path home = os.path.expanduser("~") data_dir = os.path.join(home, ".todo") os.makedirs(data_dir, exist_ok=True) return os.path.join(data_dir, "todos.db")

将初始化逻辑放在这里,用户第一次执行命令时自动创建目录和数据库文件,完全无感。这也是命令行工具“零配置启动”的关键做法。

5. 常见问题与排查技巧实录

5.1 数据库文件损坏怎么办

SQLite 本身很可靠,但它有“怕断电”和“怕多个进程同时写”的弱点。个人工具的使用场景里,最常遇到的问题是系统崩溃后数据库处于不一致状态。SQLite 有自带的完整性检查和恢复机制:

sqlite3 todos.db "PRAGMA integrity_check;"

如果输出不是ok,说明文件有问题。从备份中恢复是首选方案。所以从设计第一天起,就应该在每次成功执行写操作后自动复制一份到.backup目录,只保留最近5个备份,轮转删除。这个逻辑加上之后,数据库损坏就不再是灾难性事故,顶多损失最近几分钟的记录。

5.2 中文乱码问题

Windows 终端默认编码可能是 GBK,Python 的输出默认编码可能不一致,一跑就出现 UnicodeEncodeError 或者乱码。排查路径分三步:

第一步,检查终端编码。在 Python 里执行:

import sys print(sys.stdout.encoding)

如果是utf-8,基本安全。如果是cp936或其他,说明终端和 Python 输出编码不匹配。

第二步,强制 Python 输出 UTF-8。设置环境变量PYTHONUTF8=1,Python 3.7+ 支持 UTF-8 模式。也可以在代码开头加:

sys.stdout.reconfigure(encoding="utf-8")

第三步,Windows 终端启用 VT 处理。在 Windows 10 以上的 cmd 或 PowerShell 里执行chcp 65001切换到 UTF-8 代码页。

这条问题表面上是代码问题,本质上是环境问题。处理思路就是同时解决代码侧和终端侧,缺一不可。

5.3 误删怎么办

命令行工具最大的痛点是没有“回收站”。一旦执行rm 42,这条事项立刻消失。三个层级来防护:

第一层是行为设计。删除操作不物理删除,而是把状态改为archived。这样list默认看不到,但数据还在。真要物理清理,单独提供purge命令。

第二层是确认机制。对purge这种不可逆操作,要求用户输入将删除的数量计数来进行二段确认。比如它提示“将永久删除3条记录,输入3继续”,避免手滑。

第三层是备份策略。前面提过的自动备份在这里就是最后一道保险,最多恢复到几分钟前。

5.4 命令响应慢

个人工具一般不会遇到性能问题,但有一种情况会让命令慢到无法忍受:数据库文件被同步网盘(比如 OneDrive、Dropbox)自动备份,文件锁导致写操作阻塞。排查时先确认数据库文件是否落在同步目录里。如果是,把~/.todo目录加入同步排除列表,或者干脆把数据库放在本地非同步目录。

还有一个常被忽略的性能点:datetime('now', 'localtime')在每条插入时都要计算一次本地时区,理论上会影响超大批量插入的性能。对个人工具无所谓,但如果真写了导入脚本要批量插几千条记录,建议提前算好时间字符串再写入,能缩短不少执行时间。

6. 进阶扩展的几种方向

6.1 自然语言解析

基础版只支持结构化参数,进阶版可以支持更自然的输入:

todo add 周五前完成项目报告 todo add 每天下午检查服务器日志

第一种可以拆成“解析日期短语 + 提取剩余文本作为标题”。周五需要根据今天是星期几推算下一个周五。第二种“每天下午”涉及重复规则,建议引入现有的规则表达式方案,不要自己硬写。

这块的复杂度会快速上升,但也是工具从“能用”变成“好用”的关键一步。

6.2 定时提醒

命令行工具向外的通知能力很弱,这是它的天然短板。但可以通过假借系统能力弥补:

  • Linux 下用notify-send发桌面通知
  • macOS 下用osascript调通知中心
  • Windows 下用 PowerShell 弹 Toast 通知

配合系统的定时任务(cron、launchd、任务计划程序),每天检查一次到期待办并推送通知。这部分代码不难,难的是各平台兼容。建议抽一个notifier.py模块,根据sys.platform分发到对应实现。

6.3 与编辑器集成

命令行待办事项应用一个很好玩的玩法是绑定快捷键:在 Vim 里按<leader>t创建一个当前 buffer 内的待办,在 VS Code 里用任务运行器执行todo add。这样工作流完全打通——写代码时发现的 bug 变成了一条待办,写完代码顺手todo list检查一下还有哪些遗留。

数据层不变,只是增加一个调用入口,成本极低,收益很大。

6.4 同步方案

想实现多设备同步,一个轻量方案是把 SQLite 数据库文件放进私有 Git 仓库。每次操作后自动 commit 推送到远程,另一台设备 pull 下来就能看到更新。冲突确实会有,但个人使用场景下冲突概率极低。这个方案的好处是不依赖任何第三方待办服务,数据始终在自己手里。

7. 最后再讲几句实在话

写这个工具的过程中,我踩的最深的坑不是技术,而是“过度设计”。一开始我总想加更多功能——子任务、依赖关系、番茄钟、看板视图——后来发现这些功能恰恰是很多现成工具做不好的原因。命令行工具的优势在于轻、快、可脚本化,一旦功能堆叠起来,它的优势就被稀释了。

把基础六件事做到极致,比做五十个半吊子功能有价值得多。数据模型设计好了,后续扩展都是加法;数据模型乱了,后面每一次迭代都在还债。

如果你也想写一个自己的命令行工具,我的建议是:先用最简单的方案把核心流程跑通,别想着一步到位。真正用起来之后,你会自然发现哪里顺手、哪里别扭,迭代方向会变得非常清晰。这个工具是我现在每天用最频繁的软件之一,虽然它只有几百行代码,但它完全长在了我的使用习惯上,这是任何通用软件都给不了的体验。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 22:59:12

Java代码块详解:静态、构造、同步与执行顺序

说个我实际碰到过的场景。之前在某项目里做代码评审&#xff0c;看到一段工具类里写了好几个 static 代码块&#xff0c;每个都有上百行&#xff0c;还有人在静态块里做远程服务调用。我当时就问了一句"这段代码是每次调用都会走吗"&#xff0c;对方沉默了半天&#…

作者头像 李华
网站建设 2026/10/14 22:59:03

MFC自绘控件实战:CStaticEx扩展CStatic实现渐变背景与悬停交互

简介&#xff1a;CStaticEx扩展静态文本框是一份面向MFC界面开发者的轻量级控件源码&#xff0c;针对原生CStatic功能单一、难以满足美化需求的问题&#xff0c;提供背景透明、文字颜色与字体样式设置、内容动态修改、链接与手型光标、Flash闪烁文字等六项扩展能力&#xff0c;…

作者头像 李华
网站建设 2026/10/14 22:58:59

加分二叉树:中序序列下的区间DP建模与最优树构造

1. 这道题到底在考什么&#xff1a;从“加分二叉树”四个字看透本质“P1040 加分二叉树”这个标题&#xff0c;乍一看像一道普通的数据结构题&#xff0c;但括号里紧跟着的“区间DP&记忆化搜索”才是真正的题眼。它不是让你手动画一棵二叉树去凑分&#xff0c;而是用动态规…

作者头像 李华
网站建设 2026/10/14 22:58:30

剔除骑行路上的“三颗沙子”:身体、钱包与心态的持久热爱指南

骑了这么多年车&#xff0c;周围一起出发的人换了好几拨。有人第一年热情高涨&#xff0c;天天刷圈速&#xff0c;第二年就把车挂在闲鱼上&#xff1b;有人跟着买了全套顶级装备&#xff0c;骑了三次就落灰&#xff1b;还有人膝盖疼了两个月&#xff0c;从此看见坐垫就心里发怵…

作者头像 李华
网站建设 2026/10/14 22:58:23

SpringBoot药店管理系统实战:销售库存一体化设计

1. 药店管理的真实痛点&#xff1a;为什么我需要一套销售与库存一体化的系统做这个项目之前&#xff0c;我先后接触过两家规模不大的连锁药店&#xff0c;它们的经营方式非常有代表性&#xff1a;前台收银用一套简单的开单软件&#xff0c;后台库存靠库管员在 Excel 里手工维护…

作者头像 李华
网站建设 2026/10/14 22:58:09

LunarLander强化学习实战:DQN改进与训练避坑指南

简介&#xff1a;面向强化学习初学者与TensorFlow使用者&#xff0c;基于LunarLander登月器环境的强化学习案例提供了一套完整可运行的Python工程&#xff0c;解决从环境搭建、模型训练到效果验证的实践痛点。资源共6个文件&#xff0c;核心为3个Python脚本&#xff0c;分别承担…

作者头像 李华