//
Python2.x版本中,我们经常会用到异步的调用函数的功能,今天我们简单介绍一下异步执行Python函数的写法,要想实现异步调用Python函数,有几个概念需要了解。
1、装饰器
Python中的装饰器本质上的作用就是为已经存在的函数或者对象添加额外的逻辑功能。装饰器返回的对象也是一个函数对象,它经常被用在一些性能测试、日志追加、事务处理、权限校验等场景。有了装饰器,我们就可以将一些插件式的功能给拆分出来,简化代码逻辑。下面写一个简单的装饰器(翻译成英文就是wrapper)大家感受下:
代码语言:javascript复制#encoding=utf-8
定义装饰器
def debug(func):
def wrapper():
print('[DEBUG]: enter {}()'.format(func.__name__))
print('hello,')
return func()
return wrapper
#启用装饰器
@debug
def say_world():
print('world!')
say_world()
"""
执行结果
[DEBUG]: enter say_world()
hello,
world!
"""
可以看到,我们定义了一个装饰器debug,debug需要传入一个函数func,然后打印出来func的名字,再打印一个hello,然后我们用这个装饰器装饰一下下面的函数say_world,say_world打印单词world,这样,我们调用一下say_world,就会把装饰器debug中的内容也打印出来,相当于实现了say_world函数的功能追加。
如果say_world函数变的稍微复杂一点,需要传递参数,那么装饰器中也需要适当的做一点调整,如下:
代码语言:javascript复制#encoding=utf-8
#定义带参数的装饰器,注意*args和**kwargs
def debug(func):
def wrapper(*args, **kwargs):
print('[DEBUG]: enter {}()'.format(func.__name__))
print('the person info is:')
return func(*args, **kwargs)
return wrapper
#使用装饰器
@debug
def person_info(name,age):
print("the name is {},age is {}".format(name,age))
#带参数的函数
person_info("yeyz",)
"""
执行结果
[DEBUG]: enter person_info()
the person info is:
the name is yeyz,age is 26
"""
其中*args是 用来将参数打包成tuple给函数体调用的,而**kwargs 打包关键字参数成dict给函数体调用
2、Thread函数
构造方法: Thread(group=None, target=None, name=None, args=(), kwargs={})
group: 线程组,目前还没有实现,库引用中提示必须是None; target: 要执行的方法; name: 线程名; args/kwargs: 要传入方法的参数。
实例常用方法: isAlive(): 返回线程是否在运行。正在运行指启动后、终止前。 get/setName(name): 获取/设置线程名。 is/setDaemon(bool): 获取/设置是后台线程(默认前台线程(False))。(在start之前设置)
如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,主线程和后台线程均停止 如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止 start(): 启动线程。 join([timeout]): 阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout(可选参数)。
注意,我们这里标注了target和args以及start方法,这几个是我们在开启异步执行函数时候要用到的功能,其他的可以仅做了解,有兴趣可以研究。
我们给出异步执行函数的方法,如下:
代码语言:javascript复制---------------文件-----------
#coding:utf-8
from threading import Thread
def async_call(fn):
def wrapper(*args, **kwargs):
#通过target关键字参数指定线程函数fun
Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
-------------文件----------------
from time import sleep
import datetime
from async_call import async_call
class AA:
@async_call
def hello(self):
print("time1 is ",datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
sleep()
print("time2 is ",datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
return
if __name__ == "__main__":
print("time0 is ", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
AA().hello()
'''
结果
('time0 is ', '2019-12-04 21:25:34')
('time1 is ', '2019-12-04 21:25:34')
('time2 is ', '2019-12-04 21:25:36')
'''
这个方法中结合了装饰器和thread类,其中:
装饰器名称是async_call,参数是fn,装饰器中使用了thread函数,该函数开启一个新的线程去执行参数fn。
在上面例子中,我们把hello这个函数传递给装饰器async_call,然后再wrapper中去创建新线程thread,然后调用thread的start方法开始执行hello函数,最终得到我们想要的结果。
有帮助的话还希望点下再看哈