小言_互联网的博客

提升Python os.system调用Shell的执行效率

284人阅读  评论(0)

前言

 

最近做了一个SDN流表的实验,在这个实验中,需要批量删除大量的流表项,使用了shell脚本。然而,我的流表数据存放在python字典中,我一开始是考虑每次读取一个字典并构造一条指令调用os.system(),然后发现这种方法效率非常糟糕。

我考虑问题可能出现在os.system()的调用上,可能它是一种非常费时间的调用(相比于直接用shell处理数据)。

但是麻烦的是,这个SDN项目控制器基于python,我没法直接用shell写控制器程序。

所以然后想了一些办法提升它的执行效率,即本文内容。

本文适用于有大量python数据需要shell进一步处理的环境。

 

实验和方法

 

我写了两个程序,用来测试每次循环调用os.system的执行时间以及直接使用shell的执行时间,如下所示。

Python:


  
  1. import os
  2. import time
  3. start1= time. clock()
  4. os.system( './shell_test.sh')
  5. end1= time. clock()
  6. start2= time. clock()
  7. for i in range( 0, 1001):
  8. command = 'echo ' + str(i)
  9. os.system(command)
  10. end2= time. clock()
  11. start3= time. clock()
  12. for i in range( 0, 1001):
  13. command = 'echo ' + str(i) + ' &'
  14. os.system(command)
  15. end3= time. clock()
  16. print 'For Cycle in Shell: ' + str(end1-start1) + 's'
  17. print 'For Cycle in Python Command: ' + str(end2-start2) + 's'
  18. print 'For Cycle in Python Command with &: ' + str(end3-start3) + 's'

Shell:


  
  1. #! /bin/bash
  2. i=0
  3. start=$(date +%s%N)
  4. start_ms= ${start:0:16}
  5. while [ $i -le 1000 ]
  6. do
  7. echo "$i"
  8. let i=i+1
  9. done
  10. end=$(date +%s%N)
  11. end_ms= ${end:0:16}
  12. echo "cost time is: "
  13. 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()并行执行(最后有一个&)。

 

执行结果:


  
  1. For Cycle in Shell: 0. 000317s(cost time is: . 018886
  2. For Cycle in Python Command: 0. 167936s
  3. 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
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场