前言
最近做了一个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
转载:https://blog.csdn.net/yyd19981117/article/details/117337964