yonubear
Posts: 90
Joined: Thu Sep 12, 2013 11:11 pm

run a function every x min

Sun Dec 01, 2013 6:41 pm

I know this is a simple piece of code but I am sort of lost I need to run a function every 5min or so however I have had no luck in getting it to do what I want the biggest issue is I don't want it to sleep between runs I want it to simply run the function then return to the main code and simply do it again in 5min

Thanks,
Yonu

User avatar
DougieLawson
Posts: 36178
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website Twitter

Re: run a function every x min

Sun Dec 01, 2013 6:53 pm

Cron is you friend.

crontab -e

Add a line

Code: Select all

5 * * * * /home/pi/my_script_to_run_every_five_minutes
save the file (and it will be installed as your new crontab).

Obviously with a more sensible name for your script.

You can use crontab -l to see what's in your crontab.
Note: Having anything humorous in your signature is completely banned on this forum. Wear a tin-foil hat and you'll get a ban.

Any DMs sent on Twitter will be answered next month.

This is a doctor free zone.

yonubear
Posts: 90
Joined: Thu Sep 12, 2013 11:11 pm

Re: run a function every x min

Sun Dec 01, 2013 7:10 pm

thanks but I actually meant a function inside the script not the actual script

yonu

User avatar
Douglas6
Posts: 4770
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: run a function every x min

Sun Dec 01, 2013 7:34 pm


User avatar
FLYFISH TECHNOLOGIES
Posts: 1750
Joined: Thu Oct 03, 2013 7:48 am
Location: Ljubljana, Slovenia
Contact: Website

Re: run a function every x min

Sun Dec 01, 2013 7:54 pm

Hi,
yonubear wrote:thanks but I actually meant a function inside the script not the actual script
I'd reconsider your algorithm and codeflow. Running a periodic task each 5 minutes is ideal job for cron.

If your issue is to run just one function from existing script file, then you should create additional standalone script file containing a code line to call this function... and execute it.


Best wishes, Ivan Zilic.
Running out of GPIO pins and/or need to read analog values?
Solution: http://www.flyfish-tech.com/FF32

User avatar
Douglas6
Posts: 4770
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: run a function every x min

Sun Dec 01, 2013 8:11 pm

I can think of any number of situations where a cron job would not be appropriate. Say, an auto-save function in a text editor or other interactive app.

User avatar
FLYFISH TECHNOLOGIES
Posts: 1750
Joined: Thu Oct 03, 2013 7:48 am
Location: Ljubljana, Slovenia
Contact: Website

Re: run a function every x min

Sun Dec 01, 2013 8:57 pm

Hi,
Douglas6 wrote:I can think of any number of situations where a cron job would not be appropriate. Say, an auto-save function in a text editor or other interactive app.
I agree that primarly with interactive apps you can find several cases when cron might not be proper tool... but I'd not consider them as "simple piece of code", what is a (misleading?) phrase from the original message...

Anyway, when the question has "I won't tell you any details" connotation, then we can shoot all over the field in all directions... ;-)


Best wishes, Ivan Zilic.
Running out of GPIO pins and/or need to read analog values?
Solution: http://www.flyfish-tech.com/FF32

KenT
Posts: 758
Joined: Tue Jan 24, 2012 9:30 am
Location: Hertfordshire, UK
Contact: Website

Re: run a function every x min

Sun Dec 01, 2013 9:23 pm

If you want to do it in python you will need some sort of multithreading. One has been suggested above. Another alternatives, especially if you want some sort of gui is to use Tkinter, specifically root.after(time, callback) With this you are not guaranteed to get a particular interval, just the minimum guaranteed interval. If you want something guaranteed then look for a python library that uses the real time clock.
Pi Presents - A toolkit to produce multi-media interactive display applications for museums, visitor centres, and more
Download from http://pipresents.wordpress.com

yonubear
Posts: 90
Joined: Thu Sep 12, 2013 11:11 pm

Re: run a function every x min

Wed Dec 04, 2013 1:19 am

thanks for the info all I have been reading up on the timer however I have a dumb question I assume it need to be in a while loop to run every 30sec, 1min, etc. and if I place it in a while will that while look take up the majority of cpu time or will it only function when the timer is active.

Sorry to be so stupid :)
yonu

User avatar
FLYFISH TECHNOLOGIES
Posts: 1750
Joined: Thu Oct 03, 2013 7:48 am
Location: Ljubljana, Slovenia
Contact: Website

Re: run a function every x min

Wed Dec 04, 2013 2:19 am

Hi yonu,
yonubear wrote:will that while look take up the majority of cpu time or will it only function when the timer is active.
Check it out... start this loop-code and (in another terminal window) execute top command, which will display few details.


Best regards, Ivan Zilic.
Running out of GPIO pins and/or need to read analog values?
Solution: http://www.flyfish-tech.com/FF32

User avatar
Douglas6
Posts: 4770
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: run a function every x min

Wed Dec 04, 2013 3:04 am

No. The Timer makes use of a very useful feature of an OS like Linux called 'multi-threading". This means your code can continue running while another process, your timer, runs (roughly) in parallel. Your timer counts down until it is ready to run, does its thing, and then can start over, all by itself

Let's see if I can code up an example.

Code: Select all

#!/usr/bin/python
from threading import Timer
import time

def stopAndDoThis():
  # your interrupt 'call-back'
  print "Wait, I need you to do this"
  # restart the timer
  timerAgain = Timer(10, stopAndDoThis)
  timerAgain.start()

# start your timer
timerStart = Timer(10, stopAndDoThis)
timerStart.start()

while True:
  # your main code
  print "Doing something, dum dee dum"
  time.sleep(1)


yonubear
Posts: 90
Joined: Thu Sep 12, 2013 11:11 pm

Re: run a function every x min

Wed Dec 04, 2013 3:07 am

thanks that makes slightly more sense than what I had found will give it a go

Thanks,
Yonu

yonubear
Posts: 90
Joined: Thu Sep 12, 2013 11:11 pm

Re: run a function every x min

Wed Dec 04, 2013 4:00 am

ok sorry I think I am losing it do i put what i want to happen on the timer in the function where it says wait or down where it says main code?

sorry,
yonu

ame
Posts: 3172
Joined: Sat Aug 18, 2012 1:21 am
Location: Korea

Re: run a function every x min

Wed Dec 04, 2013 5:09 am

In stopAndDoThis, remove the line that says "print" and replace it with the stuff you want to do.

yonubear
Posts: 90
Joined: Thu Sep 12, 2013 11:11 pm

Re: run a function every x min

Wed Dec 04, 2013 2:02 pm

thank I was thinking that but wasn't sure.

Thanks,
Yonu

yonubear
Posts: 90
Joined: Thu Sep 12, 2013 11:11 pm

Re: run a function every x min

Wed Dec 04, 2013 8:01 pm

Ok that works great now to ask I want to do another thread and I better off calling the function at the end of the first one or is it more complicated than that.

Thanks,
Yonu

User avatar
Douglas6
Posts: 4770
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: run a function every x min

Thu Dec 05, 2013 12:10 am

It depends on what you want to happen. If you want to call another function that also runs every five minutes, immediately after the first one, then yes, just call it in the same timer thread call-back function (stopAndDoThis). If you need to run it on a different schedule, say, every 12 minutes, THEN you'll need to create and start a new timer thread.

yonubear
Posts: 90
Joined: Thu Sep 12, 2013 11:11 pm

Re: run a function every x min

Thu Dec 05, 2013 3:11 pm

question about the threading timers if I want a 5min gap between runs should I split the difference between the 2 timers or just pick one and set it at 5min? I have everything working how I want it now I just have to get the timing how I want it.

Thanks,
Yonu

User avatar
Douglas6
Posts: 4770
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: run a function every x min

Thu Dec 05, 2013 4:36 pm

Simpler is better. If you need just one timer, use just one timer.

yonubear
Posts: 90
Joined: Thu Sep 12, 2013 11:11 pm

Re: run a function every x min

Wed Dec 11, 2013 2:11 am

hey would it be possible to get a second set of eyes on this code I had everything working or atleast I thought I did but now that I have all the hardware assembled I notice it rus twice on the timer then stops and sets there but doesn't exit the script.I am hopeing that I am just overlooking something.

Code: Select all

import RPIO
import threading
import time
import subprocess
import sys, string, select
from socket import *
import RPi.GPIO as GPIO 
GPIO.setmode(GPIO.BCM)

# GPIO 23 & 17 set up as inputs, pulled up to avoid false detection.
# Both ports are wired to connect to GND on button press.
# So we'll be setting up falling edge detection for both
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# GPIO 24 set up as an input, pulled down, connected to 3V3 on button press
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
# now we'll define two threaded callback functions
# these will run in another thread when our events are detected
doors = GPIO.input(17)
windows = GPIO.input(23)
temp = None
def read_onewire_temp():
    '''
    Read in the output of /sys/bus/w1/devices/28-*/w1_slave
    If the CRC check is bad, wait and try again (up to 20 times).
    Return the temp as a float, or None if reading failed.
    '''
    crc_ok = False
    tries = 0
    global temp
    temp = None
    while not crc_ok and tries < 20:
        # Bitbang the 1-wire interface.
        s = subprocess.check_output('cat /sys/bus/w1/devices/28-*/w1_slave', shell=True).strip()
        lines = s.split('\n')
        line0 = lines[0].split()
        if line0[-1] == 'YES':  # CRC check was good.
            crc_ok = True
            line1 = lines[1].split()
            rtemp = float(line1[-1][2:])/1000
            temp = rtemp * 9 / 5 + 32 #convert temp to F
        # Sleep approx 20ms between attempts.
        time.sleep(0.02)
        tries += 1
    return temp

def stat_update(): #status update every 5 min
 global doors
 global windows
 global temp

 #read_onewire_temp()

 if doors == 1:
     hbdoors = "doorsclosed"
 else:
     hbdoors = "doorsopened"
 if windows == 1:
     hbwindows = "windowsclosed"
 else:
     hbwindows = "windowsopened"
 print ("stats Sent " + time.strftime("%I:%M:%S") + " " + time.strftime("%d/%m/%Y"))
 statSock = socket(AF_INET,SOCK_DGRAM)
 statSock.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
 msg = "xpl-trig\n{\nhop=1\nsource=storage-pi.cannon\ntarget=*\n}\nsensor.basic\n{\ndevice=storage-pi.cannon\ntype=input\ncurrent=" + hbdoors + "." + hbwindows + "." + str(temp) + "\n}\n"
 statSock.sendto(msg,("255.255.255.255",3865))

def SendHeartbeat():
# your interrupt 'call-back'
 print "Wait, I need you to do this"
# Sub routine for sending a heartbeat
 print ("HB Sent " + time.strftime("%I:%M:%S") + " " + time.strftime("%d/%m/%Y"))
 hbSock = socket(AF_INET,SOCK_DGRAM)
 hbSock.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
 msg = "xpl-stat\n{\nhop=1\nsource=storage-pi.cannon\ntarget=*\n}\nhbeat.app\n{\ninterval=5\nport=" + str(port) + "\n}\n"
 hbSock.sendto(msg,("255.255.255.255",3865))
 #time.sleep(10) #not sure if need to slow xpl sending
 stat_update()

  # restart the timer
timerAgain = threading.Timer(10, SendHeartbeat)
timerAgain.start()

def my_callback(channel): #Doors
 global doors
 if GPIO.input(17):
	print ("pin 17 Door open " + time.strftime("%I:%M:%S") + " " + time.strftime("%d/%m/%Y"))
	sndSock = socket(AF_INET,SOCK_DGRAM)
	sndSock.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
	msg = "xpl-trig\n{\nhop=1\nsource=storagepi.cannon\ntarget=*\n}\nDoorOpen\n{\ninterval=5\nport=" + str(port) + "\n}\n"
	sndSock.sendto(msg,("255.255.255.255",3865))
 else:
	print ("pin 17 Door close " + time.strftime("%I:%M:%S") + " " + time.strftime("%d/%m/%Y"))
	sndSock = socket(AF_INET,SOCK_DGRAM)
	sndSock.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
	msg = "xpl-trig\n{\nhop=1\nsource=storagepi.cannon\ntarget=*\n}\nDoorClosed\n{\ninterval=5\nport=" + str(port) + "\n}\n"
	sndSock.sendto(msg,("255.255.255.255",3865))

def my_callback2(channel): #Windows
 global windows
# windows = GPIO.input(23)
 if GPIO.input(23):
	print ("pin 23 Windows open " + time.strftime("%I:%M:%S") + " " + time.strftime("%d/%m/%Y"))
	sndSock = socket(AF_INET,SOCK_DGRAM)
	sndSock.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
	msg = "xpl-trig\n{\nhop=1\nsource=storagepi.cannon\ntarget=*\n}\nWindowOpen\n{\ninterval=5\nport=" + str(port) + "\n}\n"
	sndSock.sendto(msg,("255.255.255.255",3865))
 else:
	print ("pin 23 Windows close " + time.strftime("%I:%M:%S") + " " + time.strftime("%d/%m/%Y"))
	sndSock = socket(AF_INET,SOCK_DGRAM)
	sndSock.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
	msg = "xpl-trig\n{\nhop=1\nsource=storagepi.cannon\ntarget=*\n}\nWindowClosed\n{\ninterval=5\nport=" + str(port) + "\n}\n"
	sndSock.sendto(msg,("255.255.255.255",3865))

# when a falling edge is detected on port 17, regardless of whatever 
# else is happening in the program, the function my_callback will be run
GPIO.add_event_detect(17, GPIO.BOTH, callback=my_callback, bouncetime=300)
# when a falling edge is detected on port 23, regardless of whatever 
# else is happening in the program, the function my_callback2 will be run
# 'bouncetime=300' includes the bounce control written into interrupts2a.py
GPIO.add_event_detect(23, GPIO.BOTH, callback=my_callback2, bouncetime=300)
# Define maximum xPL message size
buff = 1500
# Define xPL base port
port = 3865

# Initialise the socket
UDPSock = socket(AF_INET,SOCK_DGRAM)
addr = ("0.0.0.0",port)

print "xPL Monitor for Python, bound to port " + str(port)
#SendHeartbeat()

# start your timer
timerStart = threading.Timer(1, SendHeartbeat)
timerStart.start()

while True:
    #print "Doing something, dum dee dum"
    time.sleep(1)

Thanks,
Yonu

User avatar
Douglas6
Posts: 4770
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: run a function every x min

Wed Dec 11, 2013 2:46 am

Check your indentation on the two lines after # restart the timer. Python is very picky about indentation. You're starting the timer twice, and never restarting it.

Then the program enters your infinite loop where it does nothing.

yonubear
Posts: 90
Joined: Thu Sep 12, 2013 11:11 pm

Re: run a function every x min

Wed Dec 11, 2013 3:07 am

thanks I didn't even notice that must have done it when I was taking out comments from where I was sorting through issues that fixed it.

Thanks,
Yonu

Return to “Python”