0

I wrote a program that checks a log file every 5 seconds for a specifig word. When it finds that word it will make some noise and overwrite the Log file. The Problem is after some point I get:

RuntimeError: maximum recursion depth exceeded while calling a Python object.

Is there a better way to make that loop?

import time
import subprocess
global playalarm

def alarm():
    if "No answer" in open("/var/log/hostmonitor.log").read():
        print "Alarm!"
        playalarm=subprocess.Popen(['omxplayer','/root/Alarm/alarm.mp3'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,close_fds=True)
        log = open("/var/log/hostmonitor.log","w")
        log.write("Checked")
        log.close()
        time.sleep(5)
        playalarm.stdin.write('q')
        alarm()
    else:
        print"Checked"
        time.sleep(5)
        alarm()

alarm()
ADTank
  • 85
  • 1
  • 2
  • 6
  • 3
    What you think of as the "local scope" of a function is stored in a data structure that gets pushed onto a stack when a method is entered and popped when the method exits. Since you are infinitely calling the alarm function, without any calls ever completing, you exceed the maximum stack depth (which is finite), and see this error. The simple fix is to use a loop instead of recursion. – Asad Saeeduddin Aug 06 '15 at 07:28

3 Answers3

6

You could just use infinity loop like

def alarm():
    while True:
        if "No answer" in open("/var/log/hostmonitor.log").read():
            print "Alarm!"
            playalarm=subprocess.Popen(['omxplayer','/root/Alarm/alarm.mp3'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,close_fds=True)
            log = open("/var/log/hostmonitor.log","w")
            log.write("Checked")
            log.close()
            time.sleep(5)
            playalarm.stdin.write('q')
        else:
            print"Checked"
            time.sleep(5)

This error

RuntimeError: maximum recursion depth exceeded

you get because infinity recursive calls of alarm() function. Every recursive call require some amount of stack memory. Stack space is finite, and after a certain number of recursive calls stack will be overflowed. To guard against this situation, Python limits the maximum depth of recursion.
In your case you don't need recursion at all.

kvorobiev
  • 5,012
  • 4
  • 29
  • 35
5

Every time alarm() calls itself, you use a little more stack space, eventually running out because the supply is not infinite.

What you need instead is a loop along the lines of:

def alarm():
    while True:
        if "No answer" in open("/var/log/hostmonitor.log").read():
            print "Alarm!"
            playalarm=subprocess.Popen(['omxplayer','/root/Alarm/alarm.mp3'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,close_fds=True)
            log = open("/var/log/hostmonitor.log","w")
            log.write("Checked")
            log.close()
            time.sleep(5)
            playalarm.stdin.write('q')
        else:
            print"Checked"
            time.sleep(5)

But you should keep in mind that the only way to end that program is to kill it off (with CTRL-C or kill, for example). It may be worthwhile re-thinking it so you can shut it down in a cleaner fashion.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
4

Use while True

code:

def func():
    while true:
        #Remaining function

For more on while loop look in to this SO question

while True will run forever you have to stop it using Ctrl+c or using a break inside the loop

Community
  • 1
  • 1
The6thSense
  • 8,103
  • 8
  • 31
  • 65