python使用装饰器和线程限制函数执行时间的方法

| 收藏本文 下载本文 作者:随便看看吧

下面是小编整理的python使用装饰器和线程限制函数执行时间的方法(共含9篇),欢迎您阅读,希望对您有所帮助。同时,但愿您也能像本文投稿人“随便看看吧”一样,积极向本站投稿分享好文章。

python使用装饰器和线程限制函数执行时间的方法

篇1:python使用装饰器和线程限制函数执行时间的方法

作者:lele 字体:[增加 减小] 类型:

这篇文章主要介绍了python使用装饰器和线程限制函数执行时间的方法,主要涉及timelimited函数的使用技巧,非常具有实用价值,需要的朋友可以参考下

本文实例讲述了python使用装饰器和线程限制函数执行时间的方法,分享给大家供大家参考。具体分析如下:

很多时候函数内部包含了一些不可预知的事情,比如调用其它软件,从网络抓取信息,可能某个函数会卡在某个地方不动态,这段代码可以用来限制函数的执行时间,只需要在函数的上方添加一个装饰器,timelimited(2)就可以限定函数必须在2秒内执行完成,如果执行完成则返回函数正常的返回值,如果执行超时则会抛出错误信息。

# -*- coding: utf-8 -*-from threading import Threadimport timeclass TimeoutException(Exception): passThreadStop = Thread._Thread__stop#获取私有函数def timelimited(timeout): def decorator(function): def decorator2(*args,**kwargs):class TimeLimited(Thread): def __init__(self,_error= None,): Thread.__init__(self) self._error = _error def run(self): try:self.result = function(*args,**kwargs) except Exception,e:self._error =e def _stop(self): if self.isAlive:ThreadStop(self)t = TimeLimited()t.start()t.join(timeout)if isinstance(t._error,TimeoutException): t._stop() raise TimeoutException(‘timeout for %s‘ % (repr(function)))if t.isAlive(): t._stop() raise TimeoutException(‘timeout for %s‘ % (repr(function)))if t._error is None: return t.result return decorator2 return decorator@timelimited(2)def fn_1(secs): time.sleep(secs) return ‘Finished‘if __name__ == “__main__”: print fn_1(4)

希望本文所述对大家的Python程序设计有所帮助,

篇2:Python装饰器

Python中的装饰器的概念经常会让人搞得一头雾水,所以今天就好好来分析一下python中的装饰器.

先看一个简单的装饰器用法:

复制代码

1 def decorator(func):

2  print(“this is wrapper”)

3

4  def wrapper():

5    func()

6

7  return wrapper

8

9

10 @decorator

11 def func():

12  print('this is func')

13

14 # func()

15 # print(func.__name__)

复制代码

运行一下上述代码,看看输出.再把14,15行的注释放开,看看输出.

我们发现当14,15行注释掉时,输出this is wrapper,

15行注释放开,你会发现先func()的名字变成了wrapper。

@其实就是python中的一个语法糖.装饰器的本质以上述代码为例:

@decorator

def func():

print('this is func')

其实解释器执行了这么一句:func = decorator(func).这就是装饰器最本质最核心的东西了.

func作为参数传递给decorator,decorator的返回值是wrapper(),赋给func.就这样被修饰的函数func其实已经变成了另一个函数wrapper了.

下面我们就来看看几个例子:

1.你想写这样一个装饰器:

@decorator

def func(user):

print(“this”,user,“ func”)

要怎么写呢?

我们来看看func = decorator(func).

第一步:我们知道decorator(func)应该返回一个函数.所以有如下代码.

def decorator(func):

def wrapper():

pass

return wrapper

第二步:装饰器是用来装饰函数的,你不能把原有的要装饰的func(user)的功能给弄没了啊.所以我们补全wrapper()

def decorator(func):

def wrapper(user):

print(“start decorate”,user)

func(user)

return wrapper

这时候你要装饰的func(user)就变成wrapper(user)啦.

完整代码:

2.一个装饰器想装饰好几个函数.

比如:

复制代码

@decorator

def func(user):

print(user)

@decorator

def func2(user1,user2):

print(user1,“and”,user2)

复制代码

要装饰的函数的参数你不确定有几个.可以用*args,**args表示任意参数就可以了.

复制代码

def decorator(func):

def wrapper(*args,**kwargs):

print(“start decorate”)

func(*args)

return wrapper

@decorator

def func(user):

print(user)

@decorator

def func2(user1,user2):

print(user1,“and”,user2)

func('tim')

func2('joe','jimmy')

复制代码

3.多个装饰器修饰一个函数

@decorator0

@decorator1

def func():

print(“this is func”)

实际上解释器执行func = decorator0(decorator1(func))

可以分两步:

1.decorator1(func)返回一个函数

2.decorator0()接受一个函数作为参数,并返回一函数.

所以就有了:

def decorator1(func):

def wrapper():

print(“decorator1!”)

func()

return wrapper

def decorator0(func):

def wrapper():

print(“decorator0!”)

func()

return wrapper

完整代码

复制代码

#func = decorator0(decorator1(func))

def decorator0(func):

def wrapper():

print(“decorator0!”)

func()

return wrapper

def decorator1(func):

def wrapper():

print(“decorator1!”)

func()

return wrapper

@decorator0

@decorator1

def func():

print(“this is func”)

print(func.__name__)

func()

复制代码

4.装饰器带参数

@decorator(num)

def func(user):

print(user)

实际上解释器执行func = decorator(num)(func)

也就是说你可以认为1.decorator(num)返回一个函数.2.返回的函数的类型是:以func为参数,返回值是一个函数.

所以第一步:

def decorator(num):

def wrapper():

pass

return wrapper

第二步:

复制代码

def decorator(num):

def wrapper(func):

def wrapper2(user):

print(num)

func(user)

return wrapper2

return wrapper

篇3:python的装饰器

由于函数也是一个对象,而且函数作为一个特殊的对象可以被赋值给其他变量(value = pringname),相反,通过变量也是可以调用函数的,以下是一个简单的例子:

1 >>>def printName():

2 ... print(“My name is Jobs”)

3 ...

4 >>>name = printName

5 >>>

6 >>>printName()

7 My name is Jobs

8 >>>name()

9 My name is Jobs

由以上代码我们不难看出,printName()函数被赋值给name变量,同样用name变量也可以调用printName()函数,此时他们是相同的,在这里说一点小知识:函数对象有

一个__name__属性,可以拿到函数的名字:

例子:

1 >>>

2 >>>name.__name__

3 'printName'

4 >>>printName.__name__

5 'printName'

6

7

现在,假设我们要增强printName函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改printName函数的定义,这种在代码运行期间动态增加功能的方式,称之为“

装饰器”(Decorator)。本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:

例子一:

1 >>>

2 >>>def log(func):

3 ... def wrapper(*args,**kw):

4 ... print 'call %s()' %func.__name__

5 ... return func(*args,**kw)

6 ... return wrapper

7 ...

观察上面的log,因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。我们要借助Python的@语法,把decorator置于函数的定义处:

1 >>>@log

2 ... def printName():

3 ... print(“My name is Jobs”)

4 ...

5 >>>printName()

6 call printName()

7 My name is Jobs

例子二:

1 >>>

2 >>>@log

3 ... def printAge():

4 ... print '%s,my age is 120' %printName()

5 ...

6 >>>job = printAge()

7 call printAge()

8 call printName()

9 My name is Jobs

10 None,my age is 120

当你调用printName或者printAge()时,不仅会调用函数本身,而且会调用在调用该函数之前打印一些日志。把@log放在printAge()函数之前相当于执行了语句:

name= log(printName)

由于log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的printName()了新的函数,于是调用printName()将执行新函数,即在log()函数中返回的wrapper()函数。

wrapper()函数的参数定义是(*args, **kw),因此,wrapper()函数可以接受任意参数的调用。在wrapper()函数内,首先打印日志,再紧接着调用原始函数。

如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。比如,要自定义log的文本:

1 def log(text):

2  def decorator(func):

3    def wrapper(*args, **kw):

4      print '%s %s():' % (text, func.__name__)

5      return func(*args, **kw)

6    return wrapper

7  return decorator

这个3层嵌套

1 >>>def log(text):

2 ...  def decorator(func):

3 ...    def wrapper(*args,**kw):

4 ...      print '%s %s():' %(text,func.__name__)

5 ...      return func(*args,**kw)

6 ...    return wrapper

7 ...  return decorator

8 ...

9 >>>@log('excute')

10 ... def printName():

11 ...  print(“My name is Jobs!”)

12 ...

13 >>>printName()

14 excute printName():

15 My name is Jobs!

16 >>>

我们来剖析上面的语句,首先执行log('execute'),返回的是decorator函数,再调用返回的函数,参数是now函数,返回值最终是wrapper函数,

以上两种decorator的定义都没有问题,但还差最后一步。因为我们讲了函数也是对象,它有__name__等属性,但你去看经过decorator装饰之后的函数,它们的__name__已经从原来的'printName变成了'wrapper':

>>>printName.__name__

'wrapper'

>>>

因为返回的那个wrapper()函数名字就是'wrapper',所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

不需要编写wrapper.__name__ = func.__name__这样的代码,Python内置的functools.wraps就是干这个事的,所以,一个完整的decorator的写法如下:

1 >>>def log(func):

2 ...  @functools.wraps(func)

3 ...  def wrapper(*args,**kw):

4 ...    print 'call %s():' %func.__name__

5 ...    return func(*args,**kw)

6 ...  return wrapper

7 ...

8 >>>

也可以针对呆参数的decorator:

import functools

def log(text):

def decorator(func):

@functools.wraps(func)

def wrapper(*args, **kw):

print '%s %s():' % (text, func.__name__)

return func(*args, **kw)

return wrapper

return decorator

这是一个更新的例子,希望帮助大家理解:

1 >>>def deco(func):

2 ...  def _deco(a,b):

3 ...    print (“before myfunc() called.”)

4 ...    ret = func(a,b)

5 ...    print(“after called.result:%s” %ret)

6 ...    return ret

7 ...  return _deco

8 ...

9

10 >>>@deco

11 ... def myfunc(a,b):

12 ...  print(“myfunc(%s,%s) called.”%(a,b))

13 ...  return a+b

14 ...

15 >>>myfunc(1,2)

16 before myfunc() called.

17 myfunc(1,2) called.

18 after called.result:3

19 3

20 >>>

补充说明:

其实,装饰器就是一个函数,一个可以用来包装函数的函数,最后返回一个修改之后的函数(这里的修改,比如增加日志,如上例。)将其重新赋值原来的标识符,并永久丧失对原始函数对象的访问。

篇4:Python 装饰器使用过程中的误区

大家都知道装饰器是一个很著名的设计模式,经常被用于AOP(面向切面编程)的场景,较为经典的有插入日志,性能测试,事务处理,Web权限校验Cache等,

Python语言本身提供了装饰器语法(@),典型的装饰器实现如下:

@function_wrapper def function(): pass

@实际上是python2.4才提出的语法糖,针对python2.4以前的版本有另一种等价的实现:

def function(): pass function = function_wrapper(function)

篇5:Python 装饰器使用过程中的误区

函数包装器 - 经典实现

def function_wrapper(wrapped): def _wrapper(*args, **kwargs):return wrapped(*args, **kwargs) return _wrapper @function_wrapper def function: pass

类包装器 - 易于理解

class function_wrapper(object): def __init__(self, wrapped):self.wrapped = wrapped def __call__(self, *args, **kwargs):return self.wrapped(*args, **kwargs) @function_wrapper def function(): pass

篇6:Python 装饰器使用过程中的误区

当我们谈到一个函数时,通常希望这个函数的属性像其文档上描述的那样,是被明确定义的,例如__name____doc__

针对某个函数应用装饰器时,这个函数的属性就会发生变化,但这并不是我们所期望的。

def function_wrapper(wrapped): def _wrapper(*args, **kwargs):return wrapped(*args, **kwargs) return _wrapper @function_wrapper def function(): pass >>>print(function.__name__) _wrapper

python标准库提供了functools.wraps(),来解决这个问题。

import functools def function_wrapper(wrapped): @functools.wraps(wrapped) def _wrapper(*args, **kwargs):return wrapped(*args, **kwargs) return _wrapper @function_wrapper def function(): pass >>>print(function.__name__) function

然而,当我们想要获取被包装函数的参数(argument)或源代码(source code)时,同样不能得到我们想要的结果。

import inspect def function_wrapper(wrapped): ... @function_wrapper def function(arg1, arg2): pass >>>print(inspect.getargspec(function)) ArgSpec(args=[], varargs='args', keywords='kwargs', defaults=None) >>>print(inspect.getsource(function)) @functools.wraps(wrapped) def _wrapper(*args, **kwargs):return wrapped(*args, **kwargs)

篇7:Python 装饰器使用过程中的误区

尽管大家实现装饰器所用的方法通常都很简单,但这并不意味着它们一定是正确的并且始终能正常工作。

如同上面我们所看到的,functools.wraps可以帮我们解决__name____doc__的问题,但对于获取函数的参数(argument)或源代码(source code)则束手无策。

本文系OneAPM工程师编译整理。OneAPM是中国基础软件领域的新兴领军企业,能帮助企业用户和开发者轻松实现:缓慢的程序代码和SQL语句的实时抓取。想阅读更多技术文章,请访问OneAPM官方技术博客。

篇8:Python 装饰器使用过程中的误区

当包装器(@function_wrapper)被应用于@classmethod时,将会抛出如下异常:

class Class(object): @function_wrapper @classmethod def cmethod(cls):pass Traceback (most recent call last):File “”, line 1, inFile “”, line 3, in ClassFile “”, line 2, in wrapperFile “.../functools.py”, line 33, in update_wrapper setattr(wrapper, attr, getattr(wrapped, attr)) AttributeError: 'classmethod' object has no attribute '__module__'

因为@classmethod在实现时,缺少functools.update_wrapper需要的某些属性,

这是functools.update_wrapper在python2中的bug,3.2版本已被修复,参考bugs.python.org/issue3445。

然而,在python3下执行,另一个问题出现了:

class Class(object): @function_wrapper @classmethod def cmethod(cls):pass >>>Class.cmethod() Traceback (most recent call last):File “classmethod.py”, line 15, inClass.cmethod()File “classmethod.py”, line 6, in _wrapper return wrapped(*args, **kwargs) TypeError: 'classmethod' object is not callable

这是因为包装器认定被包装的函数(@classmethod)是可以直接被调用的,但事实并不一定是这样的。被包装的函数实际上可能是描述符(descriptor),意味着为了使其可调用,该函数(描述符)必须被正确地绑定到某个实例上。关于描述符的定义,可以参考docs.python.org/2/howto/descriptor.html。

篇9:python实现线程池的方法

作者:liujian0616 字体:[增加 减小] 类型:转载

这篇文章主要介绍了python实现线程池的方法,实例分析了Python线程池的原理与相关实现技巧,需要的朋友可以参考下

本文实例讲述了python实现线程池的方法,分享给大家供大家参考。具体如下:

原理:建立一个任务队列,然多个线程都从这个任务队列中取出任务然后执行,当然任务队列要加锁,详细请看代码

文件名:thrd_pool.py 系统环境:ubuntu linux & python2.6

import threadingimport timeimport signalimport osclass task_info(object): def __init__(self): self.func = None self.parm0 = None self.parm1 = None self.parm2 = Noneclass task_list(object): def __init__(self): self.tl = [] self.mutex = threading.Lock() self.sem = threading.Semaphore(0) def append(self, ti): self.mutex.acquire() self.tl.append(ti) self.mutex.release() self.sem.release() def fetch(self): self.sem.acquire() self.mutex.acquire() ti = self.tl.pop(0) self.mutex.release() return ticlass thrd(threading.Thread): def __init__(self, tl): threading.Thread.__init__(self) self.tl = tl def run(self): while True:tsk = self.tl.fetch()tsk.func(tsk.parm0, tsk.parm1, tsk.parm2) class thrd_pool(object): def __init__(self, thd_count, tl): self.thds = [] for i in range(thd_count):self.thds.append(thrd(tl)) def run(self): for thd in self.thds:thd.start()def func(parm0=None, parm1=None, parm2=None): print ‘count:%s, thrd_name:%s‘%(str(parm0), threading.currentThread().getName())def cleanup(signo, stkframe): print (‘Oops! Got signal %s‘, signo) os._exit(0)if __name__ == ‘__main__‘: signal.signal(signal.SIGINT, cleanup) signal.signal(signal.SIGQUIT, cleanup) signal.signal(signal.SIGTERM, cleanup) tl = task_list() tp = thrd_pool(6, tl) tp.run() count = 0 while True: ti = task_info() ti.parm0 = count ti.func = func tl.append(ti) count += 1 time.sleep(2) pass

执行方式:python thrd_pool.py

执行结果:

count:0, thrd_name:Thread-1count:1, thrd_name:Thread-2count:2, thrd_name:Thread-3count:3, thrd_name:Thread-4count:4, thrd_name:Thread-5count:5, thrd_name:Thread-1count:6, thrd_name:Thread-6count:7, thrd_name:Thread-2count:8, thrd_name:Thread-3count:9, thrd_name:Thread-4count:10, thrd_name:Thread-5count:11, thrd_name:Thread-1count:12, thrd_name:Thread-6count:13, thrd_name:Thread-2count:14, thrd_name:Thread-3(‘Oops! Got signal %s‘, 15)

希望本文所述对大家的Python程序设计有所帮助,

约瑟夫问题的Python和C++求解方法

Python的Bottle框架中返回静态文件和JSON对象的方法

python在windows和linux下获得本机本地ip地址方法小结

python使用装饰器和线程限制函数执行时间的方法(共9篇)

欢迎下载DOC格式的python使用装饰器和线程限制函数执行时间的方法,但愿能给您带来参考作用!
推荐度: 推荐 推荐 推荐 推荐 推荐
点击下载文档 文档为doc格式

相关文章

热门推荐

HOT

猜你喜欢

NEW
点击下载本文文档