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

通过X-CTU控制脚本启停遇问题:adxl345test.py无法被终止求助

Troubleshooting: Unable to Terminate adxl345test.py via Zigbee/XBee Control

Let's break down why your current setup isn't stopping the data collection script, and walk through fixes to get it working reliably.

Key Issues in Your Current Code

  1. shell=True creates an extra process layer: When you use shell=True in subprocess.Popen, you're spawning a shell that runs your Python script—not the script directly. So the p variable refers to the shell, not the actual adxl345test.py process. Killing the shell leaves the script running as an orphan process.
  2. Serial port reinitialized every loop: Opening a new serial connection on every iteration is inefficient and can cause connection glitches.
  3. Uninitialized p variable: If you send "stop" before "run", your script will throw a NameError because p isn't defined.
  4. No process state checks: You don't verify if the script is already running before starting it, or if it's still active before trying to stop it.

Revised Working Code

Here's a fixed version of zb_control.py that addresses all these issues:

import serial
import time
import subprocess
import os
import signal

# Initialize serial connection once (outside loop to avoid repeated openings)
try:
    ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=2)
    print("Serial connection established successfully")
except serial.SerialException as e:
    print(f"Failed to open serial port: {e}")
    exit(1)

# Track the data collection process (initialize to None)
data_process = None

while True:
    # Read and decode serial input (convert bytes to string)
    incoming_cmd = ser.readline().strip().decode('utf-8')
    if not incoming_cmd:
        continue  # Skip empty lines from serial
    
    if incoming_cmd == 'run':
        # Only start if no active process exists
        if data_process is None or data_process.poll() is not None:
            print("---------------")
            print("Collecting data")
            print("---------------")
            # Spawn the script directly (no shell=True) to target the actual process
            data_process = subprocess.Popen(
                ["python3", "/home/pi/adxl345test.py"],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                start_new_session=True  # Optional: for killing child processes too
            )
        else:
            print("Data collection is already running")
    
    elif incoming_cmd == 'stop':
        # Only stop if the process is active
        if data_process is not None and data_process.poll() is None:
            try:
                # First try graceful termination (SIGTERM)
                os.killpg(os.getpgid(data_process.pid), signal.SIGTERM)
                data_process.wait(timeout=2)  # Wait for script to exit cleanly
                print("-----------------------")
                print("Script stopped gracefully")
                print("-----------------------")
            except subprocess.TimeoutExpired:
                # Force kill if graceful stop fails (SIGKILL)
                os.killpg(os.getpgid(data_process.pid), signal.SIGKILL)
                print("-----------------------")
                print("Script force-killed")
                print("-----------------------")
            finally:
                data_process = None  # Reset process tracker
        else:
            print("No active data collection script to stop")
    
    # Small delay to reduce CPU usage
    time.sleep(0.1)

Critical Fixes Explained

  1. Avoid shell=True: By using ["python3", "/home/pi/adxl345test.py"], we directly spawn the Python process. Now data_process refers to the actual script, so killing it stops the data collection.
  2. Process state tracking: We check data_process.poll() (returns None if the process is running) to prevent duplicate starts and invalid stop attempts.
  3. Graceful + force termination: We first send SIGTERM to let the script clean up (e.g., close the CSV file properly), then use SIGKILL if it doesn't exit within 2 seconds.
  4. Process group killing: The start_new_session=True flag creates a new process group, so os.killpg kills the script and any child processes it spawns (useful if your data collection script uses subprocesses).

Additional Verification Steps

  • After sending "run", check the process ID with ps aux | grep adxl345test.py to confirm it's running.
  • After sending "stop", re-run the above command to ensure the PID is gone.
  • If the CSV file still appears to grow immediately after stopping, wait a few seconds—this is often OS disk caching, not the script still running.

内容的提问来源于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 03:53:06