树莓派Python多线程脚本启动后停止执行问题求助
From what you've described, your script is freezing after starting the start_laps thread because one of two common gotchas is blocking your main thread from continuing to listen for Bluetooth data. Let's break this down and fix it step by step.
The Most Likely Culprits
1. You're accidentally waiting for the thread to finish (join() mishap)
If you called lap_thread.join() right after starting the thread, your main thread will grind to a halt until the start_laps thread completes. Since start_laps is probably running a loop (to handle lap tracking), this means your main thread will never get back to listening for new Bluetooth commands.
2. Your Bluetooth listening logic isn't in a persistent loop
Bluetooth's recv() method is blocking by default—it waits until data comes in before moving on. If your main thread only runs the listen logic once (instead of looping), it'll stop after the first data packet, even if you started a thread.
Fixes You Can Implement Right Away
1. Ditch unnecessary join() and keep the main thread listening
Wrap your Bluetooth data reception in an infinite loop, and start the thread without forcing the main thread to wait for it. Here's a revised code example that addresses this:
import json import bluetooth import threading import time # Use a thread-safe flag to control the lap thread lap_active = threading.Event() lap_thread = None def start_laps(data): lap_active.set() # Mark lap as running while lap_active.is_set(): # Your lap processing logic goes here (e.g., timing, logging) print(f"Processing lap with data: {data}") time.sleep(1) # Prevent CPU spiking print("Lap thread stopped") def main(): global lap_thread # Set up Bluetooth server server_sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) server_sock.bind(("", bluetooth.PORT_ANY)) server_sock.listen(1) port = server_sock.getsockname()[1] service_uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee" bluetooth.advertise_service(server_sock, "PiLapTracker", service_id=service_uuid) print(f"Waiting for Bluetooth connection on port {port}") client_sock, client_info = server_sock.accept() print(f"Connected to {client_info}") try: # Keep listening for Bluetooth commands indefinitely while True: data = client_sock.recv(1024) if not data: break # Connection closed # Parse incoming command cmd = json.loads(data.decode("utf-8")) if cmd["action"] == "start_lap": if not lap_active.is_set(): # Start the thread WITHOUT calling join() lap_thread = threading.Thread(target=start_laps, args=(cmd["data"],)) lap_thread.daemon = True # Auto-exit when main thread ends lap_thread.start() print("Lap tracking started") elif cmd["action"] == "stop_lap": lap_active.clear() # Signal thread to stop if lap_thread: lap_thread.join(timeout=2) # Optional: Wait for clean shutdown print("Lap tracking stopped") except IOError as e: print(f"Bluetooth error: {e}") finally: # Clean up resources lap_active.clear() if lap_thread: lap_thread.join(timeout=1) client_sock.close() server_sock.close() print("Connection closed") if __name__ == "__main__": main()
2. Use threading.Event() instead of global variables
I swapped out a simple global flag for threading.Event() because it's designed for thread-safe communication—no race conditions to worry about when toggling the lap state.
3. Set threads as daemon threads
Adding lap_thread.daemon = True ensures that if your main thread exits (e.g., if the Bluetooth connection drops), the lap thread will automatically shut down instead of lingering in the background.
Quick Extra Tips
- Handle Bluetooth instability: The Raspberry Pi's Bluetooth can be flaky, so wrapping your listen loop in a try/except block prevents crashes from unexpected disconnections.
- Thread-safe resources: If
start_lapsaccesses shared files or hardware (like a display), usethreading.Lock()to prevent data corruption or hardware conflicts.
内容的提问来源于stack exchange,提问作者Sara Fuerst

