python 函数执行时间限制_python 限制函数执行时间 代码实现

# coding=utf-8

import signal

import time

def set_timeout(num, callback):

def wrap(func):

def handle(signum, frame): # 收到信号 SIGALRM 后的回调函数,第一个参数是信号的数字,第二个参数是the interrupted stack frame.

raise RuntimeError

def to_do(*args, **kwargs):

try:

signal.signal(signal.SIGALRM, handle) # 设置信号和回调函数

signal.alarm(num) # 设置 num 秒的闹钟

print('start alarm signal.')

r = func(*args, **kwargs)

print('close alarm signal.')

signal.alarm(0) # 关闭闹钟

return r

except RuntimeError as e:

callback()

return to_do

return wrap

if __name__ == '__main__':

def after_timeout(): # 超时后的处理函数

print("do something after timeout.")

@set_timeout(2, after_timeout) # 限时 2 秒

def connect(): # 要执行的函数

time.sleep(1) # 函数执行时间,写大于2的值,可测试超时

return 'connect success.'

print(connect())

注意事项:

电脑系统是win10 64位,在使用python的signal模块时报错:“AttributeError: module 'signal' has no attribute 'SIGALRM'”,这是因为signal模块可以在linux下正常使用,但在windows下却有一些限制,在python文档https://docs.python.org/2/library/signal.html#signal.signal找到了如下解释:

"On Windows, signal() can only be called with SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, or SIGTERM. A ValueError will be raised in any other case."

也就是说在windows下只能使用这几个信号:

SIGABRT

SIGFPE

SIGILL

SIGINT

SIGSEGV

SIGTERM

也可通过线程的方式 设置超时 ,主线程设置超时时间 , 杀死子线程

import time

from threading import Thread

import inspect

import ctypes

def _async_raise(tid, exctype):

"""raises the exception, performs cleanup if needed"""

tid = ctypes.c_long(tid)

if not inspect.isclass(exctype):

exctype = type(exctype)

res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))

if res == 0:

raise ValueError("invalid thread id")

elif res != 1:

# """if it returns a number greater than one, you're in trouble,

# and you should call it again with exc=NULL to revert the effect"""

ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)

raise SystemError("PyThreadState_SetAsyncExc failed")

def stop_thread(thread):

_async_raise(thread.ident, SystemExit)

def to_do():

print('子线程开始了')

time.sleep(50)

print('结束了')

if __name__ == '__main__':

t = Thread(target=to_do)

t.start()

stop_thread(t)

print('主线程结束')

下面这种方案 ,缺陷是,设置好超时后,子线程结束,主线程也不会停止,有可能会降低效率

可以将stop_thread(t) 换为 t.join( num 秒 ) 来控制 超时kill

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值