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

如何通过zb_control.py停止adxl345test.py并保持监听X-CTU指令?

解决Zigbee控制脚本启停子进程的问题

你的核心问题在于使用subprocess.call()启动adxl345test.py时,该方法是阻塞式的——它会一直等待子进程执行完毕才会继续运行zb_control.py的后续代码。这就导致当你发送"stop"指令时,zb_control.py根本没在监听串口,自然无法响应停止命令。

下面是修正后的可行方案,主要做了两点关键改动:

  • 使用subprocess.Popen()替代call(),让子进程后台运行,不阻塞主脚本
  • 保存子进程实例,方便后续精准终止,避免误杀其他进程

修改后的完整代码

import serial, time, sys, os, subprocess

# 把串口初始化移到循环外,避免重复打开端口引发冲突
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=2)
# 初始化子进程变量,用于保存adxl345test的进程实例
data_collector = None

while True:
    # 串口读取的是字节串,解码为字符串才能和指令正确匹配
    inc = ser.readline().strip().decode('utf-8')
    if inc == 'run':
        # 检查子进程是否已在运行,避免重复启动
        if data_collector is None or data_collector.poll() is not None:
            print("---------------")
            print("Collecting data")
            print("---------------")
            # 用Popen启动后台进程,直接返回进程对象,不阻塞主脚本
            data_collector = subprocess.Popen(["python", "adxl345test.py"])
        else:
            print("Data collector is already running!")
    elif inc == 'stop':
        # 检查子进程是否存在且正在运行
        if data_collector is not None and data_collector.poll() is None:
            # 先尝试优雅终止,若进程无响应再考虑用kill()强制杀死
            data_collector.terminate()
            # 等待进程彻底结束(可选)
            data_collector.wait()
            print("-----------------------")
            print("Script has been stopped")
            print("-----------------------")
            # 重置子进程变量,方便下次启动
            data_collector = None
        else:
            print("Data collector is not running!")
    # 加小延迟降低CPU占用率
    time.sleep(0.1)

关键改动解释

  1. 串口初始化移到循环外:你之前每次循环都重新打开串口,容易引发端口占用冲突,移到外部只初始化一次更稳定。
  2. 使用Popen()启动进程:这个方法会立即返回子进程对象,主脚本可以持续监听串口指令,不会被子进程阻塞。
  3. 保存子进程实例:通过data_collector变量保存进程对象,后续直接调用terminate()就能精准停止目标脚本,比pkill更安全,不会误杀其他同名进程。
  4. 进程状态检查:启动前判断进程是否已在运行、停止前判断进程是否存在,避免重复启动或无效停止的报错。
  5. 字节串解码:串口读取的内容是字节串,必须解码为字符串才能和"run"/"stop"指令正确匹配,这也是你可能遇到的隐性匹配失败问题。

关于你之前尝试方法的问题

你注释的pkill/killall方法之所以没生效,本质是call()阻塞了主脚本,elif 'stop'分支根本没机会执行。另外,代码里adxl345test.py没加引号,写成check_call(["pkill", "-9", "-f", adxl345test.py])会直接报错,正确写法应该是check_call(["pkill", "-9", "-f", "adxl345test.py"])——但即使修正了引号,主脚本被阻塞的核心问题不解决,这些代码也执行不到。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:46:36