Python函数超时,用装饰器解决

使用场景

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

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

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

在scrapy自定义下载超时时间DOWNLOAD_TIMEOUT = 15

但是,以上所说的仅仅是爬虫,实际中还会有各种各样的情况,在大佬指点下我知道了一个超级好用的函数装饰器 func_timeout

这么好的项目竟然没有关注~

func_timeout

安装:pip install func_timeout

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

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
from func_timeout import func_set_timeout

@func_set_timeout(1)
def task():
    while True:
        print('hello world')
        time.sleep(1)

if __name__ == '__main__':
    task()

output:

hello world
Traceback (most recent call last):
  File "/home/test_.py", line 13, in <module>
    task()
  File "/home/usr/python36/lib/python3.6/site-packages/func_timeout/dafunc.py", line 185, in <lambda>
    return wraps(func)(lambda *args, **kwargs : func_timeout(defaultTimeout, func, args=args, kwargs=kwargs))
  File "/home/usr/python36/lib/python3.6/site-packages/func_timeout/dafunc.py", line 101, in func_timeout
    raise FunctionTimedOut('', timeout, func, args, kwargs)
func_timeout.exceptions.FunctionTimedOut: Function task (args=()) (kwargs={}) timed out after 1.000000 seconds.

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

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

from func_timeout import func_timeout, FunctionTimedOut

...

try:

    doitReturnValue = func_timeout(5, doit, args=('arg1', 'arg2'))

except FunctionTimedOut:
    print ( "doit('arg1', 'arg2') could not complete within 5 seconds and was terminated.\n")
except Exception as e:
    # Handle any exceptions that doit might raise here

多线程中使用

那么问题来了,在使用多线程时效果如何?

在做实验时,开启多个线程去执行任务,任务里有些是超时的,抛出错误后会终端主进程,也就是该程序关闭,可以使用异常捕获。如:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from func_timeout import func_set_timeout
import time
import func_timeout

@func_set_timeout(1)
def task():
    while True:
        print('hello world')
        time.sleep(1)


if __name__ == '__main__':
    try:
        task()
    except func_timeout.exceptions.FunctionTimedOut:
        print('task func_timeout')

output:

hello world
task func_timeout

这样就可以不用中断主程序,可以继续执行后面的任务,也可以在超时后加上重试等功能,这就看自己需要了。

最后给大家一个福利,最近发现一个Pycharm的配色,仿制Sublime的 ,看起来非常舒服,地址 simoncos/pycharm-monokai

如果有推荐的主题,欢迎留言指出 ~~~

原文发布于微信公众号 - Python爬虫与算法进阶(zhangslob)

原文发表时间:2018-07-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术小站

搞定python多线程和多进程

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条...

11310
来自专栏spring源码深度学习

java基础thread——多线程的纷争(循序渐进)

正在运行的程序,是系统进行资源分配和调用的独立单位。 每一个进程都有它自己的内存空间和系统资源。

11320
来自专栏腾讯DevOps

Git内部原理介绍

git 是一个内容寻址的文件系统,其核心部分是一个简单的键值对数据库(key-value data store),可以向该数据库插入任意类型的内容,它会返回一个...

13.1K60
来自专栏python学习路

八、线程和进程 什么是线程(thread)?什么是进程(process)? 线程和进程的区别?Python GIL(Global Interpreter Lock)全局解释器锁

什么是线程(thread)? 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一...

51070
来自专栏黑泽君的专栏

Java程序的运行原理及JVM的启动是多线程的吗?

A:Java程序的运行原理     Java通过java命令会启动java虚拟机。启动JVM,等于启动了一个应用程序,也就是启动了一个进程。   ...

40520
来自专栏技术小站

Python 多线程与多进程

原文地址:http://www.cnblogs.com/whatisfantasy/p/6440585.html

13220
来自专栏orientlu

初试 Protocol Buffer

如下, 一般情况下,进行消息发送的时候,对于 c/c++, 双方统一使用相同的结构体,发送时直接按内存块丢出去,接收后内存块直接赋值给结构体即可。但是这种对于其...

14430
来自专栏python3

python3--队列Queue,管道Pipe,进程之间的数据共享,进程池Pool,回调函数callback

既打印了主进程put的值,也打印了子进程put的值,在进程中使用队列可以完成双向通信

64810
来自专栏Java架构

Java并发之Condition的实现分析

回忆 synchronized 关键字,它配合 Object 的 wait()、notify() 系列方法可以实现等待/通知模式。

8220
来自专栏友弟技术工作室

Requests库详解

requests(爬虫系列之一) 由于最近工作中,与同事对接模拟手机浏览器进行广告模拟跳转。又一次接触用到爬虫的知识,以前用过urllib + bs4 + se...

39890

扫码关注云+社区

领取腾讯云代金券