漳州专业网站建设价格,青白江区网站开发招聘,普洱市住房和城乡建设局网站,asp.net新建网站问题分析
以下是一段每隔半小时重复执行测试用例的脚本#xff0c;func是传入的测试函数#xff0c;在执行func前后#xff0c;会打印操作次数
def repeat(func, action):try:log.info(u******开始并发%s****** % action)thread_list []for i in range(repeat_count):def…问题分析
以下是一段每隔半小时重复执行测试用例的脚本func是传入的测试函数在执行func前后会打印操作次数
def repeat(func, action):try:log.info(u******开始并发%s****** % action)thread_list []for i in range(repeat_count):def run():log.info(u***第%s次并发%s%svnf开始*** % (i 1, action, concurrent_count))func(concurrent_count)log.info(u***第%s次并发%s%svnf结束***\n % (i 1, action, concurrent_count))t Thread(targetrun)t.start()thread_list.append(t)time.sleep(60 * 30)log.info(\n)except Exception as e:log.error(!!!!!![%s] failed, message is[%s]!!!!!! % (action, e.message))
这个脚本之前都能够正常执行准备的打印操作次数就是***第%s次并发%s%svnf开始***以及***第%s次并发%s%svnf结束***\n
但是今天突然发现***第5次并发实例化200vnf开始***被打印了2次这是什么情况呢
原来是掉到闭包的坑里了
上诉for循环中的run函数里面的变量i位于Enclosing嵌套函数的外层函数内部嵌套作用域
在真正执行时变量i的值可能已经变了与定义闭包时的值不同
关于作用域可以参考https://dev.zte.com.cn/topic/#/48178
上诉for循环里有个半小时的延时如果任务能否在半小时内执行完那么打印就会正常因为i的值还未发生变化。但是如果某个任务A超过半小时for循环就会进入下一次任务这时i就会发生变化当任务A执行完成时打印的次数就会是已经发生变化的i。这就是今天突然发现***第5次并发实例化200vnf开始***被打印了2次的原因
解决方案
将变量i作为参数传给run函数run函数内部再定义一个闭包由run函数来生成闭包。而不是直接在闭包中使用i。即将i作为参数传递给run的count并在run内部定义inner函数inner函数内部使用count变量。
这样count就属于run函数的Local作用域只受run函数内部影响不会受for循环中i的影响
def repeat(func, action):try:log.info(u******开始并发%s****** % action)for i in range(repeat_count):def run(count):def inner():log.info(u***第%s次并发%s%svnf开始*** % (count 1, action, concurrent_count))func(concurrent_count)log.info(u***第%s次并发%s%svnf结束***\n % (count 1, action, concurrent_count))return innert Thread(targetrun(i))t.start()time.sleep(60 * 30)log.info(\n)except Exception as e:log.error(!!!!!![%s] failed, message is[%s]!!!!!! % (action, e.message))
总结
使用Python闭包时如果是在for循环内部生成闭包并且闭包中使用了Enclosing嵌套作用域中的变量比如上面的i最好不要直接使用而是将变量作为参数传给一个函数该函数内部再定义一个闭包由该函数来生成闭包