正文共:1566 字
预计阅读时间: 4 分钟
工作中遇到一个需求就是必须顺序执行完一些python方法,这些方法其原理都是调用原本就有的shell命令对系统进行相关的操作,但每个shell命令之间是有比较强的依赖的,比如B脚本要正常执行,就必须先成功执行了A脚本,此时就必须在逻辑上确保A脚本对应的python方向比B脚本对应的python方法是先执行的。
虽然说python本身是单线程的,但因为原本开发的python系统比较复杂,所以为了确保绝对的串行运行,需要显示的通过相应的逻辑来保证,这是使用锁的一个绝佳处境。
锁的运用
锁的朴素原理很简单,一个资源被锁锁住了,其他进程没有相应的钥匙就无法获得这个资源,如果该进程一定需要这个资源,那么就需要等待其他拥有锁的进程使用完后,释放出来给自己,然后才能继续执行。
那为了实现逻辑上的串行调用,利用锁就可以轻松实现,依旧是A脚本对应的方法A要比B脚本对应的方法B先调用,那么方法A调用时,将资源使用锁锁住,只用正在使用该资源的方法A具有锁的钥匙,只有等方法A执行完,释放锁后,方法B才能获得钥匙去调用相应的锁。
这里通过threading中的Lock来实现一个锁,通过装饰器的写法实现一个装饰器,实现对方法加锁,如果方法没有执行完,锁就不会释放,此时其他方法就不能继续执行。具体代码如下:
from threading import Lock
# Program Lock. Program running when it get the program lock
lock = Lock()
def use_lock(func):
def wrapper(*args, **kwargs):
# get lock
if lock.acquire():
try:
print('%s [%f]'%(func.__name__, time.time()))
return func(*args, **kwargs)
print('%s [%f]' % (func.__name__, time.time()))
except:
print('func [%s] error'%(func.__name__))
raise
finally:
# release lock, avoid dead lock
lock.release()
return wrapper
使用的使用,如下:
@use_lock
def _start(self, mode):
...
为了确保python是串行运行对应的方法的,这里使用list将方法存放起来,然后顺序传参调用,因为调用的方法被use_lock装饰器装饰了,所以当第一个方法在运行时,第二个方法是无法运行的,而且通过顺序获取list中方法的方式,也很好的提现串行执行的想法,具体代码如下:
def startServer(self):
'''
first, start ssdb
second, start sgame
:return:
'''
try:
#顺序调用有所的方法
funcs = [self._start, self._start]
#参数
params = [('xxx1',), ('xxx2',)]
# sequential execute
for funcp in zip(funcs, params):
code,info = funcp[0](*funcp[1])
if code == errorcode:
return rt_pt(errorcode, 'ssdb and sgame start fail')
return rt_pt(successcode, 'ssdb and sgame start success')
except:
print(traceback.print_exc())
return rt_pt(errorcode, 'ssdb and sgame start fail')
小结
通过锁和list具有顺序的特性,将方法强行串行执行,让强依赖方法之间的正常使用。
网友评论