常见问题(FAQ)
如何保持脚本运行?
下面的脚本看起来应该能打开 LED:
from gpiozero import LED
led = LED(17)
led.on()
如果您使用的是 Python 或 IPython shell,或者 IDLE、Thonny 或 Mu 编辑器,它确实可以打开 LED。但是,如果将此脚本保存为 Python 文件并运行,LED 会短暂闪亮,然后脚本结束,LED 关闭。
下面的文件包含了一个有意的 pause()
来保持脚本的活力:
from gpiozero import LED
from signal import pause
led = LED(17)
led.on()
pause()
现在,脚本将一直运行,使 LED 亮起,直到手动终止(例如按下 Ctrl+C)。同样,在对按下的按钮或其他输入 设备设置回调时,脚本也需要一直运行才能检测到事件:
from gpiozero import Button
from signal import pause
def hello():
print("Hello")
button = Button(2)
button.when_pressed = hello
pause()
when_pressed, is_pressed 和 wait_for_press 有什么区别?
gpiozero 提供了一系列读取输入设备的不同方法。有时,您想询问按钮是否被按下;有时,您想在按钮被按下之前执行某些操作;有时,您想在按钮被按下时发生某些操作,而不管发生了什么。
在一个简单的例子中,按钮是唯一起作用的设备,所有选项都同样有效。但一旦引入了额外的元素,如另一个 GPIO 设备,就可能需要根据使用情况选择正确的方法。
is_pressed
是一个属性,通过返回True
或False
来显示按钮当前是否被按下:
while True:
if btn.is_pressed:
print("Pressed")
else:
print("Not pressed")
wait_for_press()
是一个阻止代码继续运行的方法,直到按钮被按下。 另请参阅wait_for_release()
:
while True:
print("Released. Waiting for press...")
btn.wait_for_press()
print("Pressed. Waiting for release...")
btn.wait_for_release()
when_pressed
是一个属性,它为按钮被按下的事件指定了一个回调函数。每次按下按钮时,回调函数都会在一个单独的线程中执行。另请参阅when_released
:
def pressed():
print("Pressed")
def released():
print("Released")
btn.when_pressed = pressed
btn.when_released = released
这种选项模式在许多设备中都很常见。所有输入设备和内部设备都有 is_active
、when_activated
、when_deactivated
、wait_for_active
和 wait_for_inactive
,许多设备还提供了别名(如 "pressed" 表示 "activated")。
另请参阅 源与值 页面中更高级的方法。
我的事件处理程序没有被调用
分配事件处理程序时,不要调用所分配的函数。例如
from gpiozero import Button
def pushed():
print("Don't push the button!")
b = Button(17)
b.when_pressed = pushed()
在上面的例子中,当赋值给 when_pressed
时,被赋值的是调用 pushed
函数的结果。由于 pushed
并没有明确返回任何内容,因此结果是 None
。因此,这等同于
b.when_pressed = None
这不会引发错误,因为它是完全有效的:当你不想让事件处理程序做任何事情时,你就会这样赋值。相反,你应该这样做:
b.when_pressed = pushed
这将把函数赋值给事件处理程序,而不会调用它。这就是 my_function
(对函数的引用)和 my_function()
(调用函数的结果)之间的关键区别。
请注意,从 v1.5 版起,将回调设置为 None
(之前为 None
)将引发 CallbackSetToNone
警告,目的是在回调意外设置为 None
时提醒用户。不过,如果这是有意为之,则可以抑制该警告。请参考 warnings
模块。
导入 gpiozero 时为什么会收到 PinFactoryFallback 警告?
您很可能是在虚拟 Python 环境中工作时忘记安装 RPi.GPIO
等引脚驱动库。GPIO Zero 依赖较低级别的引脚驱动程序来处理与 Raspberry Pi 上 GPIO 引脚的接口,因此只需安装 GPIO Zero 的首选项即可消除警告:
pip install rpi.gpio
导入 GPIO Zero 时,它会按照首选顺序(详见 API-引脚)尝试查找引脚驱动程序。如果加载第一个首选项(RPi.GPIO
)失败,它会发出警告,然后返回尝试第二个首选项,以此类推。最终,它会一直返回到 native
实现。这是 GPIO Zero 本身内置的纯 Python 实现。虽然它在大多数情况下都能工作,但几乎肯定不是你想要的(它不支持 PWM,而且在某些情况下运行速度很慢)。
如果你想使用默认引脚驱动程序以外的引脚驱动程序,并希望抑制警告,你有几个选择:
- 通过
GPIOZERO_PIN_FACTORY
环境变量明确指定所需的引脚驱动程序。例如
GPIOZERO_PIN_FACTORY=pigpio python3
在这种情况下,不会发出警告,因为没有回退机制;要么加载指定的工厂,要 么加载失败,在这种情况下会引发 ImportError
。
- 抑制警告,让回退机制发挥作用:
import warnings
warnings.simplefilter('ignore')
import gpiozero
有关过滤特定警告类的更精细方法,请参阅 warnings
模块文档。
如何判断我安装的是哪个版本的 gpiozero?
gpiozero 库依赖 setuptools 软件包提供安装服务。您可以使用 setuptools 的 pkg_resources
API 来查询 Python 环境中 gpiozero 的版本:
>>> from pkg_resources import require
>>> require('gpiozero')
[gpiozero 1.6.2 (/usr/lib/python3/dist-packages)] (/usr/lib/python3/dist-packages)
>>> require('gpiozero')[0].version
'1.6.2'
如果安装了多个版本(例如来自 pip
和 apt
),它们将不会出现在 pkg_resources.require()
方法返回的列表中。不过,列表中的第一个条目将是 import gpiozero
的版本。
如果出现 "No module named pkg_resources"(没有名为 pkg_resources 的模块)的错误,则需要安装 pip
。在 Raspberry Pi 操作系统中,可以使用以下命令完成安装:
sudo apt install python3-pip
或者使用 get-pip 安装 pip。
为什么运行 pinout 时出现 "command not found"(找不到命令)?
gpiozero 库作为 Debian 软件包可用于 Python 2 和 Python 3,但 pinout 工具无法同时在两个软件包中使用,因此只包含在 Python 3 版本的软件包中。要确保 pinout 工具可用,必须安装 "python3-gpiozero" 软件包:
sudo apt install python3-gpiozero
或者,无论 Python 版本如何,使用 pip 安装 gpiozero 都能安装命令行工具:
sudo pip3 install gpiozero
或者
sudo pip install gpiozero