Reputation: 523
I am starting to learn Python (newbie), so not much idea about the different modules etc.
Scenario that I want to simulate:
I have a program prg1.py
that I want to run for some user defined time say t
seconds. After this time (t
seconds), the program should exit. For this I am using signal.signal()
to create alarm. Below is the working code:
import signal import time import sys def receive_alarm(signum, stack): sys.exit('Exiting!') signal.signal(signal.SIGALRM, receive_alarm) signal.alarm(10) while 1: print 'Working...' time.sleep(1)
The program runs for 10 seconds and then exits as expected.
Note: The while loop below is just for testing, it would be replaced by my working code.
Now I want to implement multiple signals to do different tasks at different intervals of time.
e.g. In EVERY
:
5
seconds: execute a specific function fun1()
10
seconds: execute a specific function fun2()
, and so on... (tasks I want to perform in the program)
I tried adding another alarm as shown below, but didn't work:
import signal
import time
import sys
def receive_alarm(signum, stack):
sys.exit('Exiting!')
def receive_alarm_two(signup, stack):
print 'Call to other functions!'
signal.signal(signal.SIGALRM, receive_alarm)
signal.alarm(10)
# Second Alarm
signal.signal(signal.SIGALRM, receive_alarm_two)
signal.alarm(2)
while 1:
print 'Working...'
time.sleep(1)
This doesn't work! Simple exits without any error or exit message :(
How can this functionality be implemented?
NOTE: Use of Threads is restricted.
NOTE: As I want the program to keep listening to different signals, it can't sleep i.e. cannot use time.sleep().
Upvotes: 0
Views: 3923
Reputation: 2236
You should see if your requirements can be met by the sched
module; also, why is multithreading not allowed?
It's possible to schedule multiple tasks with a single alarm by having the alarm occur at time intervals of the greatest common divisor of the period of your scheduled events. An example is below, but it's not very robust, e.g., if any task takes very long, the timing will be inaccurate. This is fixable (keep track of time with time.time()
, and schedule the next alarm accordingly), though other problems remain (what happens if one task runs so long that the next task starts late?). My perception is that schedulers are a problem with many tricky corner cases, and that if possible you should use an existing solution, rather than writing your own.
import signal
import time
class Scheduler(object):
"""Trivial scheduler object.
Rather use sched.scheduler"""
def __init__(self):
self._tasks= [(1,self._heartbeat)]
self._tick= 0
self.stopped=False
def addtask(self,period,task):
"""Add a task to be executed every PERIOD seconds
addtask(period,task)
period: seconds
task: callable taking 'tick' argument
"""
self._tasks.append( (period,task) )
def _heartbeat(self,tick):
print 'heartbeat: %d' % tick
def _execute(self,signum,stack):
if self.stopped:
return
self._tick += 1
for period, task in self._tasks:
if 0==self._tick % period:
task(self._tick)
signal.alarm(1)
def start(self):
signal.signal(signal.SIGALRM, self._execute)
signal.alarm(1)
def stop(self):
self.stopped=True
class Stopper(object):
"""Callable to stop a scheduler"""
def __init__(self, scheduler):
self._scheduler=scheduler
def __call__(self,tick):
print 'stopping at tick',tick
self._scheduler.stop()
def task3s(tick):
print '3s task at tick',tick
def task7s(tick):
print '7s task at tick',tick
s= Scheduler()
s.addtask(10,Stopper(s))
s.start()
s.addtask(3,task3s)
s.addtask(7,task7s)
while not s.stopped:
time.sleep(0.5)
print 'mainloop...'
On my (python2) system this gives:
mainloop...
heartbeat: 1
mainloop...
mainloop...
heartbeat: 2
mainloop...
mainloop...
heartbeat: 3
3s task at tick 3
mainloop...
mainloop...
heartbeat: 4
mainloop...
mainloop...
heartbeat: 5
mainloop...
mainloop...
heartbeat: 6
3s task at tick 6
mainloop...
mainloop...
heartbeat: 7
7s task at tick 7
mainloop...
mainloop...
heartbeat: 8
mainloop...
mainloop...
heartbeat: 9
3s task at tick 9
mainloop...
mainloop...
heartbeat: 10
stopping at tick 10
mainloop...
Upvotes: 4