如何确定回调中的python作用域



在我使用python3的树莓派上,我想在传入I/O上计数脉冲。为了进行测试,我编写了一个简单的程序。

import signal
import sys
import RPi.GPIO as GPIO
import time
iTP = 40
ictr=0
def signal_handler(sig, frame):
GPIO.cleanup()
print("nOut of here!")
sys.exit(0)
def button_pressed_callback(channel):
global ictr
ictr+=1
def main():
print("Here we go!")
GPIO.setmode(GPIO.BOARD)
GPIO.setup(iTP, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(iTP, GPIO.FALLING, 
callback=button_pressed_callback, bouncetime=20)

signal.signal(signal.SIGINT, signal_handler)

sctr=0
ictr=1
while 1:
time.sleep(1)
print("====")
while sctr==ictr:
time.sleep(1)
print("busy")

while sctr!=ictr:
time.sleep(2)
print("Cnt={}".format(sctr))
ictr=0
sctr=0

main()

我想在回调中收集脉冲计数,然后处理main()中的计数。脉冲实际上在回调中被收集-即ictr按预期增加-但main()中的ictr并没有反映这一点。我从来没有超过print("busy")行,即使ictr在回调中发生了变化(通过打印验证)。我尝试了各种全局声明的组合,但似乎无法让这个变量在回调和main()之间共享。非常感谢您的帮助。

当您在main中写入ictr=1而没有首先将其声明为global时,您将其变成了一个局部变量。您有两个选项:

  1. 在其他地方初始化,并将ictr=0从循环中移除,以免使其成为main的局部。这将使main通过LEGB规则查找名称ictr,该规则将在G: global处停止。

  2. main中声明global ictr,就像在button_pressed_callback中那样。

在这种情况下,第二个选项似乎更实用。一个更好的设计选择可能是使用一个类来封装当前是全局的名称空间。

使用我在不同地方找到的信息,我能够成功地创建和使用以下代码。我不清楚为什么我在这里没有相同的作用域问题,但这工作得很好。

import RPi.GPIO as GPIO
class Handle_Interrupts:
intCnt=0

def __init__(self,ipin, bouncetime):
self.ipin=ipin
self.bouncetime=bouncetime
GPIO.setmode(GPIO.BOARD)
GPIO.setup(self.ipin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(self.ipin, GPIO.FALLING, 
self.int__callback, self.bouncetime)
def int__callback(self,channel):
self.intCnt+=1

def getCnt(self):
return(self.intCnt)

def clrCnt(self):
t=self.intCnt
self.intCnt=0
return(t)

最新更新