python-35-设置函数超时退出func_timeout并记录日志信息

Python函数超时,用装饰器解决 func_timeout
python之为函数执行设置超时时间
python利用signal自定义函数超时机制

函数装饰器func_timeout的GitHub地址

1 使用场景

我们在自定义一个函数后,会调用这个函数来完成我们想要的功能。就拿爬虫来举例,你发送请求,服务器给你响应,但是有可能服务器没有给你任何数据,无论是他识别了爬虫、还是服务器繁忙什么原因,这个时候,你的爬虫就会一直等待响应,这个时候就会非常浪费资源,还会造成程序阻塞。

(1)好在requests和scrapy有自定义timeout时间,例如:在requests中这样写:

requests.post(url, headers=headers, 
data=data, proxies=proxies, timeout=15)

(2)在scrapy自定义下载超时时间DOWNLOAD_TIMEOUT = 15。

但是,以上所说的仅仅是爬虫,实际中还会有各种各样的情况。

2 安装使用

pip3 install func_timeout
pip3 install func_timeout-4.3.5.tar.gz

使用:在你的函数前加上装饰器,如下:

2.1 设置超时时间

from func_timeout import func_set_timeout
import func_timeout
import time


@func_set_timeout(3)
def task():
    print('hello world')
    time.sleep(5)
    return '执行成功_未超时'


if __name__ == '__main__':
    try:
        print(task())
    except func_timeout.exceptions.FunctionTimedOut:
        print('执行函数超时')

func_timeout将在指定的参数的线程中运行指定的函数,直到返回,引发异常或超时。如果存在返回或异常,则将正常返回。

可以看到使用方法很简单,直接加上想要的超时时间即可。但是会抛出异常,终止你的程序。官方提供的捕获异常方法。

2.2 记录异常日志信息

from func_timeout import func_set_timeout
import func_timeout
import sys
# 配置日志信息
import logging
# (1)%(asctime)s日志事件发生的时间--人类可读时间,如:2003-07-08 16:49:45,896
# (2)%(levelname)s该日志记录的文字形式的日志级别('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
# (3)%(filename)s pathname的文件名部分,包含文件后缀
# (4)%(message)s 日志记录的文本内容
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(filename)s - %(message)s"
logging.basicConfig(filename='my.log', level=logging.DEBUG, format=LOG_FORMAT)
# logging.debug("This is a debug log.")
# logging.info("This is a info log.")
# logging.warning("This is a warning log.")
# logging.error("This is a error log.")
# logging.critical("This is a critical log.")

@func_set_timeout(3)
def main():
    x = sys.stdin
    # 从标准输入获取数据
    for line in x:
        print(line)
        break


if __name__ == '__main__':
    try:
        main()
    except func_timeout.exceptions.FunctionTimedOut:
        logging.warning("执行函数超时")

3 signal的使用

只能用于linux环境。

import os
import signal
import sys
# 配置日志信息
import logging
# (1)%(asctime)s日志事件发生的时间--人类可读时间,如:2003-07-08 16:49:45,896
# (2)%(levelname)s该日志记录的文字形式的日志级别('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
# (3)%(filename)s pathname的文件名部分,包含文件后缀
# (4)%(message)s 日志记录的文本内容
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(filename)s - %(message)s"
logging.basicConfig(filename='my.log', level=logging.DEBUG, format=LOG_FORMAT)
# logging.debug("This is a debug log.")
# logging.info("This is a info log.")
# logging.warning("This is a warning log.")
# logging.error("This is a error log.")
# logging.critical("This is a critical log.")

def main():
    x = sys.stdin
    # 从标准输入获取数据
    for line in x:
        print(line)
        break

#定义信号处理函数
def myhandler(signum,frame):
    # os.kill(os.getpid(),signal.SIGKILL)
    logging.warning("执行函数超时")
    exit()  # 终止Python程序

if __name__ == '__main__':
    try:
        signal.signal(signal.SIGALRM,myhandler)  # 注册 signal.SIGALRM's handler 
        signal.alarm(10)  # 10秒后向进程发送SIGALRM信号
        main()
        signal.alarm(0)  # 函数在规定时间执行完后关闭alarm闹钟
    except Exception as e:
        logging.error(e)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮皮冰燃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值