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

Python指纹识别read_fingerprint函数添加超时方案咨询

为指纹读取函数添加超时的实现方案

用threading实现超时是完全合理的,也是处理这类阻塞式SDK调用的常用方案。由于你的SDK读取函数是阻塞的,主线程无法直接中断它,把读取逻辑放到子线程中执行,主线程等待指定超时时间后结束等待,同时通过线程安全的队列传递返回值,就能实现需求。

修改后的代码示例

首先补上缺失的导入:

import ctypes
import threading
import queue
import time
from typing import Union

然后修改FingerPrintReader类的read_fingerprint方法,添加超时机制:

class FingerPrintReader:

    SDK_ERRORS = {
        -23: "Not Connected",
        -22: "SDK not started",
        # 新增超时错误提示
        -99: "Read timed out"
    }

    def __init__(self):
        self.sdk = None
        try:
            self.sdk = ctypes.CDLL("/usr/lib/lib_sdk.so")
            result = self.sdk.SDK_Biometric_Start()
            if result != 1:
                print(f"ERROR: {self.SDK_ERRORS[result]}")
            print("Success!")
        except OSError as error:
            print(f"[ERROR] {error}")
    
    def read_fingerprint(self, timeout: int = 10) -> Union[bytes, None]:
        if not self.sdk:
            return None
        
        # 用队列安全传递线程执行结果
        result_queue = queue.Queue()

        def _internal_read():
            """子线程中执行阻塞的指纹读取"""
            template = bytes(b"\x00") * 669
            result = self.sdk.SDK_Biometric_ReadFingerPrint(template)
            if result == 1:
                result_queue.put(template)
            else:
                print(f"ERROR: {self.SDK_ERRORS[result]}")
                result_queue.put(None)
        
        # 启动子线程执行读取
        read_thread = threading.Thread(target=_internal_read)
        read_thread.start()
        # 等待线程结束,最多等待timeout秒
        read_thread.join(timeout=timeout)

        if read_thread.is_alive():
            # 超时处理:标记线程为守护线程,避免阻塞程序退出
            read_thread.daemon = True
            print(f"ERROR: {self.SDK_ERRORS[-99]} after {timeout} seconds")
            return None
        
        # 获取子线程的执行结果
        try:
            return result_queue.get_nowait()
        except queue.Empty:
            return None

    def save_fingerprint_as_template(self, template: bytes) -> None:
        # 把时间戳转成整数,避免文件名含小数点
        file_name = int(time.time())
        if template:
            with open(f"{file_name}.tpl", "wb") as template_file:
                template_file.write(template)

方案说明

  1. 线程安全的结果传递:用queue.Queue在子线程和主线程间传递指纹模板,避免直接共享变量带来的线程安全问题。
  2. 超时处理逻辑:主线程通过join(timeout)等待子线程,超时后检查线程是否存活,若存活则标记为守护线程(防止它阻塞程序退出)并返回超时提示。
  3. 额外优化:
    • 把SDK_ERRORS移到类内部,更符合封装原则;
    • 修复了save_fingerprint_as_template中文件名含浮点数的问题;
    • 补充了超时对应的错误提示。

其他可选方案

  • 优先SDK自带超时:如果你的指纹识别SDK的读取函数本身支持传入超时参数,直接使用SDK的原生超时会更可靠(能主动中断读取操作),这是最优解。
  • 多进程方案:用multiprocessing替代threading,但进程间通信开销更大,且如果SDK存在全局状态或资源锁,跨进程调用可能出现问题,因此一般不推荐。

内容的提问来源于stack exchange,提问作者Joey Fran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 16:25:13