You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何通过独立线程在指定时间关闭主应用与主机

实现方案说明

首先澄清核心疑问:独立线程内调用time.sleep()不会阻塞主线程。time.sleep()触发时当前线程会主动释放GIL,CPU资源会完全切给其他线程执行,哪怕线程内sleep数小时,也不会占用CPU资源、不会拖慢主扫码循环的响应速度,比依赖轮询的schedule库更适合你这台配置不高的Win10主机。
实现时不要把定时判断逻辑塞进主扫码循环,避免扫码逻辑阻塞时关机时机偏移;用独立守护线程跑时间监控最稳定,设置为daemon属性的线程会随主线程退出自动销毁,不会残留僵尸进程。
核心注意点:关机流程必须先做数据收尾,再执行系统关机,避免考勤记录未落盘丢失;扫码读取逻辑必须加短超时,不能用无限阻塞的读接口,保证到点时主循环能及时响应退出信号。

可直接调试的代码片段
import threading
import time
import datetime
import os

# 线程间共享的运行状态标志
RUNNING = True
# 配置每日自动关机时间,例如下午18点整
SHUTDOWN_TIME = (18, 0)
# 关机缓冲时长(秒),预留时间保存考勤数据、关闭硬件连接
SHUTDOWN_BUFFER = 5

def shutdown_task():
    """到点执行的关停流程:先停业务再关系统"""
    global RUNNING
    RUNNING = False
    # 等待主循环完成当前正在处理的扫码记录
    time.sleep(SHUTDOWN_BUFFER)
    # Win10系统关机命令:1秒后强制关机,调试时可注释该行替换为打印语句
    os.system("shutdown /s /t 1 /f")
    # 调试用:print("【测试】已触发关停逻辑")

def shutdown_monitor():
    """守护线程:固定间隔核对系统时间,到点触发关停"""
    print(f"定时关机监控已启动,每日{SHUTDOWN_TIME[0]}:{SHUTDOWN_TIME[1]:02d}自动关停设备")
    while RUNNING:
        now = datetime.datetime.now()
        if now.hour == SHUTDOWN_TIME[0] and now.minute >= SHUTDOWN_TIME[1]:
            print("已达设定关机时间,开始执行关停流程")
            shutdown_task()
            break
        # 每30秒核对一次时间,CPU占用可忽略,避免直接sleep到固定时间点时系统时间跳变导致触发失效
        time.sleep(30)

def main_attendance_loop():
    """扫码考勤主逻辑"""
    # 此处替换为你的扫描仪初始化、日志/数据库连接初始化代码
    print("考勤系统启动完成,等待扫码...")
    while RUNNING:
        # 注意:扫码读取必须设置短超时(0.3-0.5秒),禁止无超时阻塞调用
        try:
            # 示例:替换为你实际的扫码读取方法,timeout单位根据你的SDK调整为对应毫秒/秒值
            scan_content = usb_scanner.read(timeout=500)
            if scan_content:
                # 此处替换为你的考勤记录写入逻辑
                print(f"考勤记录:{scan_content} 时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        except Exception as e:
            print(f"扫码读取异常:{str(e)}")
            time.sleep(0.1)
    # 主循环退出后的收尾操作:关闭扫描仪连接、刷写日志、关闭数据库连接
    print("主循环已退出,正在保存未写入数据...")
    # usb_scanner.close()
    # db_connection.close()
    print("数据保存完成")

if __name__ == "__main__":
    # 启动守护线程跑关机监控
    monitor_thread = threading.Thread(target=shutdown_monitor, daemon=True)
    monitor_thread.start()
    # 启动主扫码循环
    main_attendance_loop()
低配置设备优化建议
  • 不要引入schedule库:该库本质是事件轮询,要么嵌入主循环挤占业务逻辑位置,要么单独开线程跑也会带来不必要的轮询开销,上述30秒间隔的时间核对逻辑资源占用不到schedule的1/10。
  • 调试阶段先注释系统关机命令,用打印日志验证触发时机、数据落盘逻辑完全正常后,再放开关机指令,避免调试时异常关机。
  • 不要担心GIL导致的性能问题:整个程序的两个线程绝大多数时间处于sleep、USB IO等待、文件写入IO等待状态,这类操作都会主动释放GIL,不会出现线程抢资源导致的卡顿,实际运行时CPU占用稳定在1%以内。
  • 如果需要临时取消关机,在触发缓冲时间内打开CMD执行shutdown /a即可中止关机流程。

内容的提问来源于stack exchange,提问作者Craig M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 09:15:40