错误 - UnboundLocalError:本地变量' VARIABLE_NAME'在分配之前引用

时间:2015-10-02 03:23:17

标签: python variables time callback gpio

我正在树莓派上运行一段python代码 代码的功能是将GPIO 5设置为连接了瞬时开关的上拉电阻。按下开关时,它会将上拉电阻接地。我试图使用按钮来触发回调 回调的作用如下:
如果按下按钮并检测到仍然按下它,则定义一个名为" t1"的变量。作为当前时间。
如果检测到按钮不再被按下,则定义一个名为" t2"的变量。然后减去" t1"来自" t2"找到时间差(按下按钮的时间量)。然后它将该值转换为定义为变量" deltaseconds"的整数。然后它根据按钮的长度采取行动。如果超过7秒,重新启动树莓派,如果超过1秒但小于7秒,它会在高和低之间切换输出GPIO(12)。

我遇到的问题是这样的:
代码运行
按下按钮时,我看到"按下按钮5的打印"
当按钮松开时,我看到打印"按钮5已释放"
然后错误显示为"UnboundLocalError: local variable 't1' referenced before assignment"
错误参考第21行delta = t2-t1

完整代码如下所示:

import os
import RPi.GPIO as GPIO
import webiopi
import time
import datetime
from datetime import datetime
GPIO.setwarnings(True)
GPIO.setmode(GPIO.BCM)
BUTTON_5 = 5
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(12,GPIO.OUT)
GPIO.output(12,1)
#Just to visually distinguish between setup steps and main program
def pressed(BUTTON_5):
    if GPIO.input(5) == False:
        t1 = datetime.now()
        print "Button 5 pressed"
    elif GPIO.input(5) == True:
        print "Button 5 released"
        t2 = datetime.now()
        delta = t2-t1
        deltaseconds = delta.total_seconds()
        if (deltaseconds > 7) : # pressed for > 7 seconds
            print "Restarting System"
            subprocess.call(['shutdown -r now "System halted by GPIO action" &'], shell=True)
        elif (deltaseconds > 1) : # press for > 1 < 7 seconds
            print "Toggling GPIO 12"
            GPIO.output(12, not GPIO.input(12))
GPIO.add_event_detect(BUTTON_5, GPIO.BOTH, bouncetime=200)
GPIO.add_event_callback(BUTTON_5, pressed)
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    GPIO.cleanup()       # clean up GPIO on CTRL+C exit

3 个答案:

答案 0 :(得分:0)

检查变量的范围。 t1在== False块中定义。第21行位于elif块中。当块结束时,所有局部变量都被破坏(或至少不可访问)。

要更正此问题,请添加一行以查看是否在循环开始时定义了t1,如果未定义t1,则将其定义为不合理的(您可能决定稍后检查)。

答案 1 :(得分:0)

t1应在pressed(BUTTON_5)之外定义。您希望保留从此函数的一次调用到下一个函数的值。虽然可以在python函数中使用静态变量(通过使它们成为函数的属性),但通常更清楚地使它们成为全局的(在python 2中)。所以,只需将global t1放在函数的开头。

我应该提到全局变量很快就会失控,但如果只在一个函数中访问变量,那么就没有问题了。

答案 2 :(得分:0)

经过大量的调查和学习后,我能够通过以下代码获得所需的结果:

import os
import RPi.GPIO as GPIO
import webiopi
import time  
import subprocess
import datetime
from datetime import datetime
GPIO.setwarnings(True)
GPIO.setmode(GPIO.BCM)
BUTTON_5 = 5
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(12,GPIO.OUT)
GPIO.output(12,1)
#Just to visually distinguish between setup steps and main program
t1 = 999999999999999999999
def pressed(BUTTON_5):
    if GPIO.input(5) == False:
        global t1 
        t1 = datetime.now()
        print "Button 5 pressed"
    elif GPIO.input(5) == True:
        print "Button 5 released"
        t2 = datetime.now()
        delta = t2-t1
        deltaseconds = delta.total_seconds()
        if (deltaseconds > 7) : # pressed for > 7 seconds
            print "Restarting System"
            subprocess.call(['shutdown -r now "System halted by GPIO action" &'], shell=True)
        elif (deltaseconds > 1) : # press for > 1 < 7 seconds
            print "Toggling GPIO 12"
            GPIO.output(12, not GPIO.input(12))
GPIO.add_event_detect(BUTTON_5, GPIO.BOTH, bouncetime=200)
GPIO.add_event_callback(BUTTON_5, pressed)
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    GPIO.cleanup()       # clean up GPIO on CTRL+C exit  

此代码似乎运行顺利,我已经彻底测试过了。我不得不定义&#34; t1&#34;作为一个全球变量,一旦我了解它们是什么以及它们如何运作,它们就开始落实到位。

感谢所有为此做出贡献的人。