如何在0.5秒后在python 2.4中发出警报信号

发布于 2024-12-17 10:02:18 字数 226 浏览 0 评论 0原文

我想在运行 0.5 秒后让一段特定的 python 代码超时。因此,我打算在 0.5 秒后引发异常/信号,并优雅地处理它并继续执行其余代码。

在Python中我知道signal.alarm()可以设置整数秒的闹钟。有什么替代方案可以在 0.5 秒后生成警报吗?其他帖子中建议的 signal.setitimer() 在 python2.4 中不可用,我需要使用 python2.4 来实现此目的?

I want to timeout a particular piece of python code after in runs for 0.5 seconds. So I intend to raise an exception/signal after 0.5 seconds, and handle it gracefully and continue with rest of code.

In python i know that signal.alarm() can set alarm for integer seconds. Is there any 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 I need to use python2.4 for this purpose?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吹泡泡o 2024-12-24 10:02:18

从耐心等待的“守护进程”线程发出警报。在下面的代码中,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()

Raise the alarm from a patiently waiting "daemon" thread. In the code below, snoozealarm does what you want via a SnoozeAlarm thread:

#! /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()
情绪操控生活 2024-12-24 10:02:18

您有两个选择:

  1. 轮询 time.time() 或在相关代码运行时进行类似操作。显然,只有当该代码在您的控制之下时,这才是可行的。

  2. 正如 pajton 所提到的,您可以编写一个 C 扩展来调用系统调用 setitimer()。这并不太难,因为您只需从更高版本的 Python 源代码中复制 signal.getitimer()signal.setitimer() 代码即可。它们只是同名系统调用的薄包装。

    此选项仅在您使用 CPython 并且处于允许您使用自定义 C 扩展的环境中时才可行。

    编辑:这是从 Python 2.7 中的signalmodule.c(适用 Python 许可证):

    <前><代码>#include“Python.h”
    #include

    静态 PyObject *ItimerError;

    /* setitimer/getitimer 的辅助函数 */
    静态无效
    timeval_from_double(double d, struct timeval *tv)
    {
    tv->tv_sec = 楼层(d);
    tv->tv_usec = fmod(d, 1.0) * 1000000.0;
    }

    Py_LOCAL_INLINE(双精度)
    double_from_timeval(结构 timeval *tv)
    {
    返回 tv->tv_sec + (double)(tv->tv_usec / 1000000.0);
    }

    静态 PyObject *
    itimer_retval(结构 itimerval *iv)
    {
    PyObject *r, *v;

    r = PyTuple_New(2);
    如果(r==NULL)
    返回空值;

    if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_value)))) {
    Py_DECREF(r);
    返回空值;
    }

    PyTuple_SET_ITEM(r, 0, v);

    if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_interval)))) {
    Py_DECREF(r);
    返回空值;
    }

    PyTuple_SET_ITEM(r, 1, v);

    返回 r;
    }

    静态 PyObject *
    itimer_setitimer(PyObject *self, PyObject *args)
    {
    双第一;
    双间隔=0;
    整数其中;
    结构 itimerval 新,旧;

    if(!PyArg_ParseTuple(args, "id|d:setitimer", &which, &first, &interval))
    返回空值;

    timeval_from_double(first, &new.it_value);
    timeval_from_double(间隔, &new.it_interval);
    /* 让操作系统检查“which”值 */
    if (setitimer(which, &new, &old) != 0) {
    PyErr_SetFromErrno(ItimerError);
    返回空值;
    }

    返回 itimer_retval(&old);
    }

    PyDoc_STRVAR(setitimer_doc,
    “setitimer(其中,秒[,间隔])\n\
    \n\
    设置给定的计时器(ITIMER_REAL、ITIMER_VIRTUAL 之一\n\
    或 ITIMER_PROF) 在值秒后触发\n\
    每个间隔秒。\n\
    可以通过将秒设置为零来清除定时器。\n\
    \n\
    以元组形式返回旧值:(延迟,间隔)。");

    静态 PyObject *
    itimer_getitimer(PyObject *self, PyObject *args)
    {
    整数其中;
    结构 itimerval 旧;

    if (!PyArg_ParseTuple(args, "i:getitimer", &which))
    返回空值;

    if (getitimer(which, &old) != 0) {
    PyErr_SetFromErrno(ItimerError);
    返回空值;
    }

    返回 itimer_retval(&old);
    }

    PyDoc_STRVAR(getitimer_doc,
    “获取计时器(其中)\n\
    \n\
    返回给定计时器的当前值。");

    静态 PyMethodDef itimer_methods[] = {
    {“setitimer”,itimer_setitimer,METH_VARARGS,setitimer_doc},
    {“getitimer”,itimer_getitimer,METH_VARARGS,getitimer_doc},
    {NULL, NULL} /* 哨兵 */
    };

    PyMODINIT_FUNC
    启动器(无效)
    {
    PyObject *m、*d、*x;
    整数我;
    m = Py_InitModule3("itimer", itimer_methods, 0);
    如果(m == NULL)
    返回;

    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,使用类似的内容将其编译为 C 扩展

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

    现在,如果你幸运的话,你应该能够使用 Python 导入它

    导入定时器
    

    并调用 itimer.setitimer()

You have two options:

  1. Polling time.time() or similar while the code in question runs. This is obviuosly only viable if that code is under your control.

  2. As mentioned by pajton, you could write a C extension to call the system call setitimer(). This isn't too hard because you could simply copy the code of signal.getitimer() and signal.setitimer() from the source of later versions of Python. They are just thin wrappers around the equally named system calls.

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

    Edit: Here is the code copied from signalmodule.c in Python 2.7 (Python's licence applies):

    #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 are lucky, you should be able to import this from Python using

    import itimer
    

    and call itimer.setitimer().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文