这是为您生成的定时提醒并检查待办事项脚本,它是一个 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>参数快速执行单项操作,方便集成到其他工作流中。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播