向后兼容性
GPIO Zero 2.x 是一个新的主要版本,因此向后不兼容的更改是可以预期的。我们试图将这些变化保持在合理的最小范围内,同时利用这个机会来进行清理。本章记录了从 GPIO Zero 1.x 版本到 2.x 版本的重大变化,以及所有在 2.0 版本中仍可正常工作但计划在未来 2.x 版本中删除的过时功能。
查找并修复被弃用的用法
从 2.0 版开始,所有被弃用的功能在使用时都会引发 DeprecationWarning
。默认情况下,Python 解释器会抑制这些警告(因为它们只对开发者有意义,而不是用户),但您可以很容易地配置不同的行为。
下面的示例脚本使用了一些已废弃的函数:
import gpiozero
board = gpiozero.pi_info()
for header in board.headers.values():
for pin in header.pins.values():
if pin.pull_up:
print(pin.function, 'is pulled up')
尽管使用了过时的功能,脚本仍能在 gpiozero 2.0 中正常(无声)运行。为了发现使用了哪些已废弃的函数,我们添加了几行文字,告诉警告模块我们希望 "默认" 处理 DeprecationWarning
;"默认" 处理意味着,第一次尝试在特定位置引发警告时,警告的详细信息将被打印到控制台。以后从同一位置发出的所有调用都将被忽略。这样可以避免在控制台中充斥来自紧密循环的警告细节。这样,脚本看起来就像这样了:
import gpiozero
import warnings
warnings.filterwarnings('default', category=DeprecationWarning)
board = gpiozero.pi_info()
for header in board.headers.values():
for pin in header.pins.values():
if pin.pull_up:
print(pin.function, 'is pulled up')
运行时,控制台会产生以下输出:
/home/dave/projects/home/gpiozero/gpio-zero/gpiozero/pins/__init__.py:899:
DeprecationWarning: PinInfo.pull_up is deprecated; please use PinInfo.pull
warnings.warn(
/home/dave/projects/home/gpiozero/gpio-zero/gpiozero/pins/__init__.py:889:
DeprecationWarning: PinInfo.function is deprecated; please use PinInfo.name
warnings.warn(
GPIO2 is pulled up
GPIO3 is pulled up
这告诉我们脚本中使用了哪些已废弃的功能,但并没有告诉我们在脚本的哪个位置使用了这些功能。为此,将警告转换为完整的异常更为有用。有了这一改动,每次打印 DeprecationWarning
时,脚本都会以未处理异常和完整的堆栈跟踪结束:
import gpiozero
import warnings
warnings.filterwarnings('error', category=DeprecationWarning)
board = gpiozero.pi_info()
for header in board.headers.values():
for pin in header.pins.values():
if pin.pull_up:
print(pin.function, 'is pulled up')
现在运行脚本,结果如下:
Traceback (most recent call last):
File "/home/dave/projects/home/gpiozero/gpio-zero/foo.py", line 9, in <module>
if pin.pull_up:
File "/home/dave/projects/home/gpiozero/gpio-zero/gpiozero/pins/__init__.py", line 899, in pull_up
warnings.warn(
DeprecationWarning: PinInfo.pull_up is deprecated; please use PinInfo.pull
这告诉我们脚本的第 9 行使用了已废弃的功能,并提示我们如何修复。我们将第 9 行改为使用 "pull" 属性。现在我们再次运行,这次得到的结果如下:
Traceback (most recent call last):
File "/home/dave/projects/home/gpiozero/gpio-zero/foo.py", line 10, in <module>
print(pin.function, 'is pulled up')
File "/home/dave/projects/home/gpiozero/gpio-zero/gpiozero/pins/__init__.py", line 889, in function
warnings.warn(
DeprecationWarning: PinInfo.function is deprecated; please use PinInfo.name
现在我们可以看出第 10 行有问题,异常再次告诉我们如何修复。我们继续这样做,直到脚本看起来像这样:
import gpiozero
import warnings
warnings.filterwarnings('error', category=DeprecationWarning)
board = gpiozero.pi_info()
for header in board.headers.values():
for pin in header.pins.values():
if pin.pull == 'up':
print(pin.name, 'is pulled up')
现在脚本运行完成,因此我们可以确信它不再使用任何过时的功能,即使在未来的 2.x 版本中删除了这些功能,它也能正常运行。此时,你也可以删除 filterwarnings
一行(或至少将其注释掉)。
不再支持 Python 2.x
到目前为止,最大、最重要的变化是不再支持 Python 2.x 系列(实际上,这意味着不再支持 Python 2.7)。如果您的代码与 Python 3 不兼容,则应遵循 Python 文档 中的 移植指 南。
GPIO Zero 2.0 支持的最低 Python 版本为 3.5。这个基础版本可能会随着小版本的发布而提高,但我们会尽最大努力不破坏与旧 Python 3.x 版本的兼容性,并确保 GPIO Zero 能在发布时 Debian oldstable 中的 Python 版本上运行。
删除 RPIO 引脚工厂
RPIO 引脚在 Raspberry Pi 2 以后的版本中已不支持,因此目前几乎没有实际用途。建议仍然依赖 RPIO 稳定 PWM 实现的用户尝试使用 pigpio 引脚实现(GPIO Zero 也支持)。
删除已废弃的引脚工厂别名
GPIOZERO_PIN_FACTORY
环境变量指定的引脚工厂别名已被删除:
-
删除了 "PiGPIOPin",代之以 "pigpio"。
-
删除 "RPiGPIOPin",代之以 "rpigpio"。
-
删除 "NativePin",使用 "native"。
换句话说,在调用脚本时,你不能再使用以下内容:
GPIOZERO_PIN_FACTORY=PiGPIOPin python3 my_script.py
取而代之的是
GPIOZERO_PIN_FACTORY=pigpio python3 my_script.py
关键字参数
GPIO Zero 1.x 中的许多类在其构造函数和方法中都有只包含关键字的参数。例如,PiLiter 在文档中的构造函数为 PiLiter(*, pwm=False, initial_value=False, pin_factory=None)
意味着其所有参数都只有关键字。
然而,尽管有这样的文档说明,这一点却很少被执行,因为在 Python 2.x 下要做到这一点而又不使代码库变得相当复杂是非常困难的(Python 2.x 缺乏声明仅关键字参数的 "*" 语法;它们只能通过 "**kwargs" 参数和字典操作来实现)。
在 GPIO Zero 2.0 中,所有此类参数现在实际上都是关键字参数。如果您的代码符合 1.x 版文档的要求,您应该不会注意到有什么不同。换句话说,下面的代码仍然没有问题:
from gpiozero import PiLiter
l = PiLiter(pwm=True)
但是,如果省略了关键字,则需要修改代码:
from gpiozero import PiLiter
l = PiLiter(True) # this will no longer work
机器人使用电机,PhaseEnableRobot 已被弃用
GPIO Zero 1.x 应用程序接口规定,机器人(Robot
) 由两个元组构成,而这两个元组又用于构成两个 电机(Motor
) 实例。在 2.x API 中,只需传递您希望用作左轮和右轮的 电机(Motor
) 或 PhaseEnableMotor()
实例即可。
如果您当前的代码使用针脚 4 和 14 作为左轮,使用针脚 17 和 18 作为右轮,那么它可能看起来像这样:
from gpiozero import Robot
r = Robot(left=(4, 14), right=(17, 18))
应将其改为
from gpiozero import Robot, Motor
r = Robot(left=Motor(4, 14), right=Motor(17, 18))
同样,如果您目前使用的是 PhaseEnableRobot()
,您的代码可以如下所示:
from gpiozero import PhaseEnableRobot
r = PhaseEnableRobot(left=(4, 14), right=(17, 18))