最近做了一个SDN流表的实验,在这个实验中,需要批量删除大量的流表项,使用了shell脚本。然而,我的流表数据存放在python字典中,我一开始是考虑每次读取一个字典并构造一条指令调用os.system(),然后发现这种方法效率非常糟糕。
我考虑问题可能出现在os.system()的调用上,可能它是一种非常费时间的调用(相比于直接用shell处理数据)。
但是麻烦的是,这个SDN项目控制器基于python,我没法直接用shell写控制器程序。
所以然后想了一些办法提升它的执行效率,即本文内容。
本文适用于有大量python数据需要shell进一步处理的环境。
我写了两个程序,用来测试每次循环调用os.system的执行时间以及直接使用shell的执行时间,如下所示。
Python:
import os
import time
start1=time.clock()
os.system('./shell_test.sh')
end1=time.clock()
start2=time.clock()
for i in range(0,1001):
command = 'echo ' + str(i)
os.system(command)
end2=time.clock()
start3=time.clock()
for i in range(0,1001):
command = 'echo ' + str(i) + ' &'
os.system(command)
end3=time.clock()
print 'For Cycle in Shell: ' + str(end1-start1) + 's'
print 'For Cycle in Python Command: ' + str(end2-start2) + 's'
print 'For Cycle in Python Command with &: ' + str(end3-start3) + 's'
Shell:
#! /bin/bash
i=0
start=$(date +%s%N)
start_ms=${start:0:16}
while [ $i -le 1000 ]
do
echo "$i"
let i=i+1
done
end=$(date +%s%N)
end_ms=${end:0:16}
echo "cost time is: "
echo "scale=6; ($end_ms - $start_ms)/1000000" | bc
总结一下:
我考虑了循环1000次并打印的场景,其中,python程序里我统计了三个时间,分别是:
1、调用一次shell,shell循环1000次;
2、python生成shell指令,调用1000次os.system()执行;
3、python生成shell执行,调用1000次os.system(),同时这些os.system()并行执行(最后有一个&)。
执行结果:
For Cycle in Shell: 0.000317s(cost time is: .018886)
For Cycle in Python Command: 0.167936s
For Cycle in Python Command with &: 0.171174s
我们发现,shell中执行1000次循环,其程序的本身运行时间仅需要0.018秒;
然而,如果使用python生成每一条指令并执行os.system(),其时间需要0.16秒,大约相差10倍。
如果仅考虑python中调用os.system()的时间,那么仅调用一次os.system()的时间是循环生成指令并调用的约600分之一(0.0003 VS 0.1679)
在本实验中,我们使用了os.system()的阻塞方法,若使用命令行末尾的 & 或者其他非阻塞方法,此时在理论上,我们仅需考虑python调用的时间。因此,在理想的理论情况上来看,在shell中直接执行循环的效率能够比在python中每次生成命令并调用os.system()的效率提升10到数百倍。
而利用 & 标识进行并行处理的情况和非并行的情况差不多(0.167 VS 0.171),其原因分析是:在这两种情况下,都调用了1000次os.system(),而这可能是一种费时的方法,与简单的执行指令的时间开销并不在一个数量级上。
综上所述,若python需要循环调用shell,考虑到程序运行的效率,最关键的问题在于减少os.system类指令的调用次数。
解决的思路是:将循环写入shell脚本,减少python调用shell的次数。如果shell脚本需要额外python程序中生成的参数作为输入,将其作为环境变量,传给shell脚本。
如何实现python将数组传入shell,并在shell中循环执行请参考我的另一篇博客:
https://blog.csdn.net/yyd19981117/article/details/117337487?spm=1001.2014.3001.5501