这是为您生成的定时提醒并检查待办事项脚本,它是一个 Python 工具,能在后台运行,定期检查您设定的任务列表,并在任务到期时弹出通知。

#!/usr/bin/env python3
"""
定时提醒并检查待办事项脚本
功能:
1. 从 JSON 文件中加载待办事项(可指定时间,"2025-12-31 23:59")
2. 每 30 秒检查一次是否有到期的任务(基于本地时间)
3. 如果有任务到期,通过系统通知(notify-send)提醒用户
4. 支持标记任务为已完成(从列表中移除)
5. 支持交互式添加新任务
6. 提供简单的命令行菜单
依赖:
- Python 3.6+
- Linux/Unix 环境(使用 notify-send 发送通知)
- 若使用 Windows/macOS,可自行替换通知方式(如 win10toast、pyobjc)
用法:
python todo_reminder.py # 启动提醒与检查
python todo_reminder.py --add # 添加新任务后立即退出
python todo_reminder.py --list # 列出所有待办事项
python todo_reminder.py --done <id> # 将指定 ID 的任务标记为完成
"""
import json
import os
import sys
import time
import argparse
from datetime import datetime
from threading import Thread, Event
# ---------- 配置 ----------
TODO_FILE = os.path.expanduser("~/.todo_reminder.json")
CHECK_INTERVAL = 30 # 检查间隔(秒)
# --------------------------
# 全局退出事件
exit_event = Event()
def load_tasks() -> list:
"""从 JSON 文件加载待办事项列表"""
if not os.path.exists(TODO_FILE):
return []
with open(TODO_FILE, "r", encoding="utf-8") as f:
try:
return json.load(f)
except json.JSONDecodeError:
print("警告:任务文件损坏,已重置为空列表。")
return []
def save_tasks(tasks: list):
"""保存待办事项列表到 JSON 文件"""
with open(TODO_FILE, "w", encoding="utf-8") as f:
json.dump(tasks, f, ensure_ascii=False, indent=2)
def notify(title: str, message: str):
"""发送系统通知(跨平台兼容处理)"""
# Linux 下使用 notify-send
if sys.platform.startswith("linux"):
try:
os.system(f'notify-send "{title}" "{message}"')
except Exception:
pass
# macOS 下使用 osascript
elif sys.platform == "darwin":
try:
os.system(f'osascript -e \'display notification "{message}" with title "{title}"\'')
except Exception:
pass
# Windows 下使用 win10toast(需安装:pip install win10toast)
elif sys.platform == "win32":
try:
from win10toast import ToastNotifier
toaster = ToastNotifier()
toaster.show_toast(title, message, duration=5)
except ImportError:
print(f"[通知] {title}: {message}")
else:
print(f"[通知] {title}: {message}")
def check_due_tasks(tasks: list) -> list:
"""检查所有到期任务,返回已到期的任务列表(同时自动移除重复提醒)"""
now = datetime.now().strftime("%Y-%m-%d %H:%M")
due_tasks = []
remaining = []
for task in tasks:
task_time = task.get("time", "")
if task_time and task_time <= now:
due_tasks.append(task)
else:
remaining.append(task)
return due_tasks, remaining
def show_tasks(tasks: list):
"""以编号形式显示所有待办事项"""
if not tasks:
print("✅ 当前没有待办事项。")
return
print(f"\n📋 待办事项列表(共 {len(tasks)} 项):")
print("-" * 50)
for idx, task in enumerate(tasks, 1):
time_str = task.get("time", "无时间")
desc = task.get("desc", "无描述")
print(f" {idx}. [{time_str}] {desc}")
print("-" * 50)
def add_task_interactive():
"""交互式添加新任务"""
desc = input("请输入待办事项描述:").strip()
if not desc:
print("描述不能为空,取消添加。")
return
time_str = input("请输入截止时间(格式:YYYY-MM-DD HH:MM,留空表示不指定时间):").strip()
if time_str:
try:
datetime.strptime(time_str, "%Y-%m-%d %H:%M")
except ValueError:
print("时间格式错误,请使用 YYYY-MM-DD HH:MM 格式。")
return
else:
time_str = "" # 无截止时间
tasks = load_tasks()
tasks.append({"desc": desc, "time": time_str})
save_tasks(tasks)
print(f"✅ 已添加待办事项:{desc}" + (f" (截止 {time_str})" if time_str else ""))
def mark_done(task_id: int):
"""根据序号标记任务为已完成(从列表移除)"""
tasks = load_tasks()
if task_id < 1 or task_id > len(tasks):
print(f"❌ 无效的任务编号:{task_id},当前共有 {len(tasks)} 项。")
return
removed = tasks.pop(task_id - 1)
save_tasks(tasks)
print(f"✅ 已完成:{removed['desc']}" + (f" (截止 {removed['time']})" if removed['time'] else ""))
def periodic_check():
"""定时检查循环,直到退出事件被设置"""
print(f"⏰ 提醒服务已启动,每 {CHECK_INTERVAL} 秒检查一次到期任务...")
while not exit_event.is_set():
tasks = load_tasks()
due_tasks, remaining = check_due_tasks(tasks)
if due_tasks:
for task in due_tasks:
msg = f"任务:{task['desc']}"
if task.get("time"):
msg += f"\n截止时间:{task['time']}"
notify("⏰ 待办事项提醒", msg)
print(f"\n🔔 到期提醒:{task['desc']}" + (f" (截止 {task['time']})" if task['time'] else ""))
# 保存剩余任务(已移除到期任务)
save_tasks(remaining)
# 等待指定间隔,期间可被退出事件中断
exit_event.wait(CHECK_INTERVAL)
def main_loop():
"""主交互循环:在后台运行检查线程,并提供控制台菜单"""
# 启动后台检查线程
checker = Thread(target=periodic_check, daemon=True)
checker.start()
print("\n====== 待办事项提醒工具 ======")
print("命令:")
print(" list - 列出所有待办事项")
print(" add - 添加新待办事项")
print(" done n - 标记编号 n 的任务为完成")
print(" quit - 退出程序")
print("==============================")
try:
while True:
cmd = input("\n请输入命令:").strip().lower()
if cmd == "quit":
print("正在退出...")
exit_event.set()
break
elif cmd == "list":
tasks = load_tasks()
show_tasks(tasks)
elif cmd == "add":
add_task_interactive()
elif cmd.startswith("done "):
try:
task_id = int(cmd.split()[1])
mark_done(task_id)
except (IndexError, ValueError):
print("用法:done <编号>,done 3")
else:
print("未知命令,可用命令:list, add, done n, quit")
except KeyboardInterrupt:
print("\n用户中断,正在退出...")
exit_event.set()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="定时提醒并检查待办事项")
parser.add_argument("--add", action="store_true", help="添加新任务后立即退出")
parser.add_argument("--list", action="store_true", help="列出所有待办事项")
parser.add_argument("--done", type=int, metavar="ID", help="标记指定编号的任务为完成")
args = parser.parse_args()
# 处理命令行快捷操作
if args.add:
add_task_interactive()
elif args.list:
tasks = load_tasks()
show_tasks(tasks)
elif args.done is not None:
mark_done(args.done)
else:
# 启动主交互循环
main_loop()
功能与操作说明
您可以通过命令行菜单或参数来管理任务,脚本会持续在后台检查,并在任务到期时通过系统通知提醒您。
- 任务管理:您可以通过
add、list、done <编号>命令来添加、查看和完成待办事项,所有任务会保存在~/.todo_reminder.json文件中。 - 自动提醒:脚本启动后,会每30秒检查一次任务列表,当系统时间等于或超过任务的“截止时间”时,会自动发送系统通知,并将该任务从列表中移除。
- 灵活使用:您可以直接运行脚本进入交互模式,也可以使用
--add、--list、--done <ID>参数快速执行单项操作,方便集成到其他工作流中。