Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
187 views
in Technique[技术] by (71.8m points)

python - signal.pause() with signal.alarm() causes RecursionError in non-sleeping program

Single-threaded python program, intending to be responsive to events from raspberry pi button presses also wants to wake every minute to update an LCD display.

Main function:

btn_1 = 21
GPIO.setup(btn_1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(btn_1, GPIO.FALLING, callback=btn_1_press_callback, bouncetime=100)

lcd.display()
lcd.messsage("text to display on lcd"

The previous code runs the btn_1_press_callback function whenever a physical button is pressed. The rest of the main function, instead of sleeping in a busy loop, does this:

signal.signal(signal.SIGALRM, wake_every_min)
signal.alarm(60)
signal.pause()

This way button presses are signaled immediately. The wake_every_minute() function simply refreshes the display with the currently displayed data (updating from the data source), so it updates every minute regardless of a button press:

def wake_every_min(sig, frame):
  lcd.clear()
  lcd.message("new string here")
  signal.alarm(60)
  signal.pause()

And then it calls signal.pause() to sleep / but listen for signals again. This works perfectly, except for the fact that after some time, I get RecursionError: maximum recursion depth exceeded while calling a Python object

Funny enough it's always at the same time, meaning "previous line repeated 482 times" is alway 482:

Traceback (most recent call last):
File "./info.py", line 129, in <module>
  main()
File "./info.py", line 126, in main
  signal.pause()
File "./info.py", line 111, in wake_every_min
  signal.pause()
File "./info.py", line 111, in wake_every_min
  signal.pause()
File "./info.py", line 111, in wake_every_min
  signal.pause()
[Previous line repeated 482 more times]

Is there another way to accomplish this without a while True loop with a time.sleep()? If I do that, button presses aren't responsive, as there is always a potential for a 1.9999 minute delay, worst-case.

question from:https://stackoverflow.com/questions/65860056/signal-pause-with-signal-alarm-causes-recursionerror-in-non-sleeping-program

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Update: I was thinking about this wrong. time.sleep() will not prevent a signal from happening -- the signals will interrupt sleep().

The correct solution is to sleep in the main loop, and never call signal.pause(). With a SIGINT handler, you can also exit immediately when ^c is pressed:

signal.signal(signal.SIGALRM, wake_every_min)
signal.alarm(60)
signal.signal(signal.SIGINT, int_signal_handler)
while True:
    # Sleep and wait for a signal.
    sleep(10)
    signal.alarm(60)

Moving the re-setting of the alarm into the main loop prevents RecursionError, as new signals aren't piling up from the handler call stack. If anyone is curious what this was for, it's a crypto LCD ticker: https://github.com/manos/crypto_lcd/blob/master/info.py


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
...