树莓派3B+ Python开发:全局变量替代方案及未知错误排查
Hey there! As someone who’s tinkered with Raspberry Pi and Python for years, let’s break this down clearly—since you’re new to Python, we’ll focus on practical, easy-to-adopt fixes.
全局变量的替代方案
Global variables can get messy fast (hard to debug, easy to accidentally overwrite), so here are three solid alternatives tailored to your GPIO project:
- 类封装状态:This is the cleanest approach for hardware projects. Wrap your LED, Button, and game state (like start time, reaction time) into a class. All related logic stays together, and you avoid polluting the global namespace. We’ll use this method in the example code below!
- 函数参数传递:Instead of relying on global variables, pass objects (like your LED/Button) and values directly to functions. For example:
def trigger_led(led): led.on() - 闭包共享状态:If you prefer not to use classes, you can use nested functions where the inner function has access to variables from the outer function (without making them global). This works well for smaller scripts.
可能遇到的错误及解决办法
Since you don’t have specific error messages, here are the most common issues with this type of Raspberry Pi GPIO project, plus fixes:
NameError: name 'xxx' is not defined:- Cause: You tried to modify a global variable inside a function without declaring it as
global, or you misspelled the variable name. - Fix: If you must use a global variable, add
global your_variable_nameat the start of the function. Better yet, switch to a class/parameter passing to avoid this entirely.
- Cause: You tried to modify a global variable inside a function without declaring it as
RuntimeError: Failed to add edge detection:- Cause: GPIO pins are still in use from a previous run (your program didn’t exit cleanly), or you mixed up BCM vs BOARD pin numbering.
- Fix: Restart your Raspberry Pi to free up pins, double-check your pin numbering (gpiozero uses BCM by default), and add a
KeyboardInterrupthandler to clean up resources on exit.
AttributeError: 'NoneType' object has no attribute 'xxx':- Cause: Your LED/Button object failed to initialize (wrong pin, loose wiring) and is
Nonewhen you try to use it. - Fix: Check your hardware connections, verify pin numbers, and add error handling during initialization (like a
try-exceptblock).
- Cause: Your LED/Button object failed to initialize (wrong pin, loose wiring) and is
逻辑错误(按钮无反应/触发过早):
- Cause: Global variables are being modified by multiple functions at the wrong time, leading to messed-up state.
- Fix: Use a class to encapsulate state—this ensures only controlled methods can change variables like
start_time.
优化后的代码示例(用类替代全局变量)
Here’s a cleaned-up version of your script using a class to avoid global variables, with clear game logic:
from gpiozero import LED, Button from time import sleep, time from random import uniform from sys import exit from signal import pause class ReactionGame: def __init__(self, led_pin=18, button_pin=23): # Initialize hardware components (adjust pins to match your wiring) self.led = LED(led_pin) self.button = Button(button_pin) self.start_time = None # Bind button press event to our handler self.button.when_pressed = self.on_button_press def wait_random_delay(self): # Wait a random time between 1-5 seconds before turning on the LED delay = uniform(1, 5) sleep(delay) self.led.on() self.start_time = time() # Record when the LED turned on def on_button_press(self): if self.start_time is not None: # Calculate reaction time reaction_time = time() - self.start_time print(f"Your reaction time: {reaction_time:.3f} seconds!") self.led.off() self.start_time = None # Start next round automatically self.wait_random_delay() else: print("Hold on! Wait for the LED to turn on first.") def start(self): print("Objective: Push the button as fast as you can when the LED turns on!") self.wait_random_delay() pause() # Keep the program running to listen for button presses if __name__ == "__main__": try: game = ReactionGame() game.start() except KeyboardInterrupt: print("\nGame ended.") exit(0)
内容的提问来源于stack exchange,提问作者ConnectedAccess

