How to signal an alarm on python 2.4 in 0.5 seconds

I want to timeout a specific piece of python code after running for 0.5 second. Thus, I intend to raise an exception / signal after 0.5 seconds and handle it gracefully and continue with the rest of the code.

In python, I know that signal.alarm() can set an alarm for whole seconds. Is there an alternative where we can generate an alarm after 0.5 seconds. signal.setitimer() , as suggested in other posts, is not available in python2.4, and do I need to use python2.4 for this?

+7
source share
2 answers

Raise an alarm from a patiently awaiting demon stream. In the code below, snoozealarm does what you want through the snoozealarm stream:

 #! /usr/bin/env python import os import signal import threading import time class SnoozeAlarm(threading.Thread): def __init__(self, zzz): threading.Thread.__init__(self) self.setDaemon(True) self.zzz = zzz def run(self): time.sleep(self.zzz) os.kill(os.getpid(), signal.SIGALRM) def snoozealarm(i): SnoozeAlarm(i).start() def main(): snoozealarm(0.5) while True: time.sleep(0.05) print time.time() if __name__ == '__main__': main() 
+4
source

You have two options:

  • Polling time.time() or similar while the code is executing. This is only apparent for viability if this code is under your control.

  • As mentioned in pajton, you can write a C extension to call the setitimer() system call. This is not so complicated because you can simply copy the signal.getitimer() and signal.setitimer() code from the source of later versions of Python. These are just subtle wrappers around equally named system calls.

    This option is only available if you are using CPython and you are in an environment that allows you to use custom C extensions.

    Change Here is the code copied from signalmodule.c in Python 2.7 (Python license applied):

     #include "Python.h" #include <sys/time.h> static PyObject *ItimerError; /* auxiliary functions for setitimer/getitimer */ static void timeval_from_double(double d, struct timeval *tv) { tv->tv_sec = floor(d); tv->tv_usec = fmod(d, 1.0) * 1000000.0; } Py_LOCAL_INLINE(double) double_from_timeval(struct timeval *tv) { return tv->tv_sec + (double)(tv->tv_usec / 1000000.0); } static PyObject * itimer_retval(struct itimerval *iv) { PyObject *r, *v; r = PyTuple_New(2); if (r == NULL) return NULL; if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_value)))) { Py_DECREF(r); return NULL; } PyTuple_SET_ITEM(r, 0, v); if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_interval)))) { Py_DECREF(r); return NULL; } PyTuple_SET_ITEM(r, 1, v); return r; } static PyObject * itimer_setitimer(PyObject *self, PyObject *args) { double first; double interval = 0; int which; struct itimerval new, old; if(!PyArg_ParseTuple(args, "id|d:setitimer", &which, &first, &interval)) return NULL; timeval_from_double(first, &new.it_value); timeval_from_double(interval, &new.it_interval); /* Let OS check "which" value */ if (setitimer(which, &new, &old) != 0) { PyErr_SetFromErrno(ItimerError); return NULL; } return itimer_retval(&old); } PyDoc_STRVAR(setitimer_doc, "setitimer(which, seconds[, interval])\n\ \n\ Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL\n\ or ITIMER_PROF) to fire after value seconds and after\n\ that every interval seconds.\n\ The itimer can be cleared by setting seconds to zero.\n\ \n\ Returns old values as a tuple: (delay, interval)."); static PyObject * itimer_getitimer(PyObject *self, PyObject *args) { int which; struct itimerval old; if (!PyArg_ParseTuple(args, "i:getitimer", &which)) return NULL; if (getitimer(which, &old) != 0) { PyErr_SetFromErrno(ItimerError); return NULL; } return itimer_retval(&old); } PyDoc_STRVAR(getitimer_doc, "getitimer(which)\n\ \n\ Returns current value of given itimer."); static PyMethodDef itimer_methods[] = { {"setitimer", itimer_setitimer, METH_VARARGS, setitimer_doc}, {"getitimer", itimer_getitimer, METH_VARARGS, getitimer_doc}, {NULL, NULL} /* sentinel */ }; PyMODINIT_FUNC inititimer(void) { PyObject *m, *d, *x; int i; m = Py_InitModule3("itimer", itimer_methods, 0); if (m == NULL) return; d = PyModule_GetDict(m); #ifdef ITIMER_REAL x = PyLong_FromLong(ITIMER_REAL); PyDict_SetItemString(d, "ITIMER_REAL", x); Py_DECREF(x); #endif #ifdef ITIMER_VIRTUAL x = PyLong_FromLong(ITIMER_VIRTUAL); PyDict_SetItemString(d, "ITIMER_VIRTUAL", x); Py_DECREF(x); #endif #ifdef ITIMER_PROF x = PyLong_FromLong(ITIMER_PROF); PyDict_SetItemString(d, "ITIMER_PROF", x); Py_DECREF(x); #endif ItimerError = PyErr_NewException("itimer.ItimerError", PyExc_IOError, NULL); if (ItimerError != NULL) PyDict_SetItemString(d, "ItimerError", ItimerError); } 

    Save this code as itimermodule.c , compile it to a C extension using something like

     gcc -I /usr/include/python2.4 -fPIC -o itimermodule.o -c itimermodule.c gcc -shared -o itimer.so itimermodule.o -lpython2.4 

    Now, if you're lucky, you should be able to import this from Python using

     import itimer 

    and call itimer.setitimer() .

+2
source

All Articles