讲师中心 微信公众号
AI工具推荐 视频效率加速

如何在 Flask 应用中正确启动与停止 USB 设备监控进程

陌丽君_5382

陌丽君_5382

发布时间:2026-08-06 17:06:00

|

413人浏览过

|

来源于php中文网

原创

如何在 Flask 应用中正确启动与停止 USB 设备监控进程

本文详解如何使用 pyudev.MonitorObserver 实现 Flask 中 USB 监控的可控启停,避免线程阻塞和状态不同步问题,通过线程安全封装 + 事件驱动设计确保 start/stop 可靠生效。

本文详解如何使用 `pyudev.monitorobserver` 实现 flask 中 usb 监控的可控启停,避免线程阻塞和状态不同步问题,通过线程安全封装 + 事件驱动设计确保 `start/stop` 可靠生效。

在 Flask 应用中集成 USB 设备热插拔监控(如使用 pyudev)时,一个常见误区是:手动创建额外线程并依赖全局标志(如 running = False)来控制 MonitorObserver 的生命周期。这不仅冗余,还极易导致竞态条件——因为 pyudev.MonitorObserver 本身已是独立线程,其 start() 和 stop() 方法已内置线程同步逻辑。强行嵌套线程 + while running 循环反而会干扰原生观察者机制,造成 stop() 不响应、事件仍持续触发等问题。

✅ 正确做法是:直接管理 MonitorObserver 实例的生命周期,无需额外线程或轮询循环。以下为精简、健壮、可直接运行的实现方案:

✅ 核心设计原则

  • 将 MonitorObserver 封装为单例类(如 MyObserver),提供线程安全的 start() / stop() 接口;
  • 使用 Lock 防止并发调用引发状态不一致;
  • 在事件回调中禁止直接调用 stop()(因可能触发主线程阻塞或上下文错误),应通过 Flask 路由异步触发;
  • 若需在设备接入时跳转页面(如 /new_device),应在路由层统一处理,而非在 device_event_monitor 中调用 render_template(该函数依赖 Flask 请求上下文,而 pyudev 回调运行在独立线程中,无上下文)。

✅ 推荐实现代码(含关键注释)

from flask import Flask, render_template_string, request
from flask_socketio import SocketIO
from threading import Lock
import pyudev

class USBMonitor:
    def __init__(self):
        self.context = pyudev.Context()
        self.monitor = pyudev.Monitor.from_netlink(self.context)
        self.monitor.filter_by('usb')
        self.monitor.enable_receiving()
        self.observer = None
        self._lock = Lock()

    def on_event(self, action, device):
        """USB 事件回调 —— 仅做轻量处理,避免阻塞或跨线程操作"""
        if device.subsystem == 'usb' and action == 'add' and device.device_type == 'usb_device':
            # ✅ 安全操作:发送消息到前端(通过 SocketIO)
            device_info = {
                'action': action,
                'vendor': device.get('ID_VENDOR_FROM_DATABASE', 'Unknown'),
                'model': device.get('ID_MODEL_FROM_DATABASE', 'Unknown'),
                'devpath': device.get('DEVPATH', ''),
            }
            sio.emit('usb_event', device_info)

            # ❌ 错误示例(勿在回调中执行):
            # stop()          # 跨线程调用不安全
            # return render_template(...)  # 无 Flask 上下文!

    def start(self):
        with self._lock:
            if self.observer is None:
                self.observer = pyudev.MonitorObserver(self.monitor, self.on_event)
                self.observer.start()
                print("✅ USB monitor started.")

    def stop(self):
        with self._lock:
            if self.observer is not None:
                self.observer.stop()
                self.observer = None
                print("✅ USB monitor stopped.")

# 初始化应用与监控器
app = Flask(__name__)
sio = SocketIO(app, cors_allowed_origins="*")
usb_monitor = USBMonitor()

# 前端页面(含启停按钮与实时事件展示)
@app.route('/')
def index():
    return render_template_string('''
    <!DOCTYPE html>
    <html>
    <head><title>USB Monitor Control</title></head>
    <body>
        <h2>USB Device Monitor</h2>
        <button id="startBtn">Start Monitoring</button>
        <button id="stopBtn" disabled>Stop Monitoring</button>
        <div id="log" style="margin-top:20px; font-family:monospace; white-space:pre-wrap;"></div>

        <script src="https://cdn.socket.io/4.8.1/socket.io.min.js"></script>
        <script>
            const socket = io();
            const logEl = document.getElementById('log');
            const startBtn = document.getElementById('startBtn');
            const stopBtn = document.getElementById('stopBtn');

            socket.on('usb_event', (data) => {
                const now = new Date().toISOString().slice(11, 19);
                logEl.textContent += `[${now}] ${data.action}: ${data.vendor} ${data.model}\n`;
                logEl.scrollTop = logEl.scrollHeight;
            });

            startBtn.onclick = () => fetch('/start', {method:'POST'})
                .then(() => { startBtn.disabled=true; stopBtn.disabled=false; });
            stopBtn.onclick = () => fetch('/stop', {method:'POST'})
                .then(() => { startBtn.disabled=false; stopBtn.disabled=true; });
        </script>
    </body>
    </html>
    ''')

@app.post('/start')
def start_monitor():
    usb_monitor.start()
    return '', 200

@app.post('/stop')
def stop_monitor():
    usb_monitor.stop()
    return '', 200

@app.post('/register_device')
def register_device():
    # ✅ 设备注册逻辑在此统一处理(例如接收表单数据、写入数据库)
    owner_name = request.form.get('owner_name')
    # ... 业务逻辑
    return "Device registered successfully!", 200

if __name__ == '__main__':
    # 启动 Flask + SocketIO(支持热重载)
    sio.run(app, debug=True, host='0.0.0.0', port=5000)

⚠️ 关键注意事项

  • 不要在 pyudev 回调中执行耗时或阻塞操作(如数据库写入、HTTP 请求、render_template),否则会拖慢整个监控线程;
  • 禁用 daemon=True 线程 + while running 循环:这是旧方案的典型反模式,MonitorObserver 本身已足够可靠;
  • 状态同步必须加锁:多线程环境下(如 Flask 多请求 + Observer 线程),对 observer 实例的读写需 threading.Lock 保护;
  • 前端交互推荐使用 Fetch API + Socket.IO:避免页面跳转中断监控,实现实时事件推送;
  • 生产环境需添加异常处理:如 pyudev.UdevError 捕获、USB 权限检查(Linux 下通常需 sudo usermod -aG plugdev $USER)。

通过以上重构,USB 监控的启停将变得原子、可靠且易于维护,彻底解决“调用 stop_usb_monitor() 但进程仍在运行”的核心痛点。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
flask框架如何搭建
flask框架如何搭建

搭建步骤:1、安装Python和Pip;2、创建虚拟环境;3、安装Flask;4、创建Flask应用;5、运行应用;6、访问应用。想了解更多flask框架的相关内容,可以阅读本专题下面的文章。

3695

2024.06.27

Python Flask框架
Python Flask框架

本专题专注于 Python 轻量级 Web 框架 Flask 的学习与实战,内容涵盖路由与视图、模板渲染、表单处理、数据库集成、用户认证以及RESTful API 开发。通过博客系统、任务管理工具与微服务接口等项目实战,帮助学员掌握 Flask 在快速构建小型到中型 Web 应用中的核心技能。

5644

2025.08.25

Python Flask Web框架与API开发
Python Flask Web框架与API开发

本专题系统介绍 Python Flask Web框架的基础与进阶应用,包括Flask路由、请求与响应、模板渲染、表单处理、安全性加固、数据库集成(SQLAlchemy)、以及使用Flask构建 RESTful API 服务。通过多个实战项目,帮助学习者掌握使用 Flask 开发高效、可扩展的 Web 应用与 API。

316

2025.12.15

pycharm怎么改成中文
pycharm怎么改成中文

PyCharm是一种Python IDE(Integrated Development Environment,集成开发环境),带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试、语法高亮、项目管理、代码跳转、智能提示、自动完成、单元测试、版本控制。此外,该IDE提供了一些高级功能,以用于支持Django框架下的专业Web开发。php中文网给大家带来了pycharm相关的教程以及文章,欢迎大家前来学习和阅读。

2949

2023.07.25

pycharm安装教程
pycharm安装教程

PyCharm是一款由JetBrains开发的Python集成开发环境(IDE),它提供了许多方便的功能和工具。本专题为大家带来pycharm安装教程,帮助大家解决问题。

5577

2023.08.21

如何解决pycharm找不到模块
如何解决pycharm找不到模块

解决pycharm找不到模块的方法:1、检查python解释器;2、安装缺失的模块;3、检查项目结构;4、检查系统路径;5、使用虚拟环境;6、重启PyCharm或电脑。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

738

2023.12.04

如何安装pycharm
如何安装pycharm

安装pycharm的步骤:1、访问PyCharm官方网站下载最新版本的PyCharm;2、下载完成后,打开安装文件;3、安装完成后,打开PyCharm;4、在PyCharm的主界面中等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

854

2024.02.23

python和pycharm的区别
python和pycharm的区别

Python和PyCharm是两个不同的概念,它们的区别如下:1、Python是一种编程语言,而PyCharm是一款Python集成开发环境;2、Python可以运行在各种不同的开发环境中,而PyCharm是专门为Python开发而设计的IDE等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

507

2024.02.23

Playwright 测试失败怎么办
Playwright 测试失败怎么办

Playwright测试失败专题汇集超时、定位器匹配、浏览器提前关闭、依赖与插件配置、文件上传、SSL及Docker启动等故障文章,并介绍通过截图、报告和Trace定位错误。

0

2026.10.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn