我想在運行0.5秒後超時一段特定的python代碼。所以我打算在0.5秒後發出一個異常/信號,並且正常處理它並繼續處理其餘的代碼。如何在0.5秒後在python 2.4中發出警報
在python我知道signal.alarm()
可以設置整數秒的警報。在0.5秒後我們可以產生報警嗎? signal.setitimer()
在其他文章中建議不在python2.4中可用,我需要爲此使用python2.4?
我想在運行0.5秒後超時一段特定的python代碼。所以我打算在0.5秒後發出一個異常/信號,並且正常處理它並繼續處理其餘的代碼。如何在0.5秒後在python 2.4中發出警報
在python我知道signal.alarm()
可以設置整數秒的警報。在0.5秒後我們可以產生報警嗎? signal.setitimer()
在其他文章中建議不在python2.4中可用,我需要爲此使用python2.4?
你有兩個選擇:
輪詢time.time()
或在有問題的代碼運行類似。如果該代碼在您的控制之下,這是明顯可行的。
正如pajton所述,您可以編寫一個C擴展名來調用系統調用setitimer()
。這並不難,因爲您可以簡單地複製源自更高版本Python的源代碼signal.getitimer()
和signal.setitimer()
。它們僅僅是同名系統調用的簡單包裝。
如果您使用CPython並且您處於允許使用自定義C擴展的環境中,則此選項纔可行。
編輯:這裏是signalmodule.c
in Python 2.7複製的代碼(Python的許可適用):
#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);
}
這段代碼保存爲itimermodule.c
,使用類似
gcc -I /usr/include/python2.4 -fPIC -o itimermodule.o -c itimermodule.c
gcc -shared -o itimer.so itimermodule.o -lpython2.4
把它編譯成一個C擴展現在,如果你幸運的話,你應該可以使用
import itimer
並致電itimer.setitimer()
。
絕對未經測試:但如果在線程下發生信號並在主代碼中運行計時器(輪詢'time.time()'),那麼如何運行要修剪的代碼?一旦限制被擊中,計時器就可以殺死線程...... [醜陋但是...不能工作?] – mac
@mac:不,這不起作用。你不能在Python中殺死線程。 –
@sven:代碼不受我控制。涉及很多計算和函數調用,並且很難在一個地方進行輪詢。 –
提高耐心等待的「守護進程」線程的警報。在下面的代碼,snoozealarm
你想要做什麼通過SnoozeAlarm
螺紋:
#! /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()
好主意,+1 .. –
這就是我所說的「反向」工程。 +1;) – mac
編寫C擴展是一個選項... – pajton
給誰投票決定關閉這個問題支持的想法是[這一個完全相同的副本](http://stackoverflow.com/q/3770711/146792):你真的讀過OP問題直到它結束嗎?問題是完全有效的IMO。 – mac
@mac:我認爲投票結束的人已經知道她的錯誤 - 至少她刪除了自動生成的評論。 :) –