【问题标题】:Error - UnboundLocalError: local variable 'VARIABLE_NAME' referenced before assignment错误 - UnboundLocalError:分配前引用了局部变量“VARIABLE_NAME”
【发布时间】:2015-10-02 03:23:16
【问题描述】:

我在树莓派上运行一段 python 代码。
代码的作用是将GPIO 5设置为上拉电阻,并附有瞬时开关。当按下开关时,它会将上拉电阻接地。我正在尝试使用按钮推送来触发回调。
回调的工作方式如下:
如果按钮被按下并检测到仍被按下,它将定义一个名为“t1”的变量作为当前时间。
如果检测到按钮不再按下,则定义一个名为“t2”的变量,然后从“t2”中减去“t1”以找到时间差(按下按钮的时间量)。然后将该值转换为定义为变量“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

【问题讨论】:

  • 您在上面的if 语句中将t1 设置为datetime.now(),然后您尝试在下面的elif 语句中访问它。
  • 是的! @dursk 是对的!您的 elif 条件正在运行,其中 t1 变量未定义。
  • 有道理,谢谢。话虽如此,我已经尝试过移动它,但我想我已经达到了我在这方面的专业知识的极限,因为我找不到将它放在它工作的地方。你能告诉我在哪里可以定义变量以保持值吗?

标签: python variables time callback gpio


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 因此,如果我在回调之外定义 t1,它将有一个设定值,如果 == False 块运行,它将更改 t1 的值。新值会在该块完成后存储还是恢复?
    • 块完成后该值不会恢复。 global 语句创建或修改全局变量。创建全局变量后,除非您显式删除它,否则它会一直存在直到程序完成运行,并且除非您显式修改它,否则它的值不会改变。
    【解决方案3】:

    经过大量的调查和学习,我能够使用以下代码达到预期的结果:

    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  
    

    这段代码似乎运行顺利,我已经对其进行了彻底的测试。我不得不将“t1”定义为一个全局变量,一旦我了解了它们是什么以及它们是如何工作的,这一切就开始到位了。

    感谢所有帮助我得到这个答案的人。

    【讨论】:

      猜你喜欢
      • 2020-08-13
      • 1970-01-01
      • 2014-08-20
      • 1970-01-01
      • 2021-10-25
      • 2020-07-29
      • 2015-05-18
      • 2019-09-11
      • 2017-08-10
      相关资源
      最近更新 更多