python调用shell命令之三大方法


 


前言: 如何直接在python代码里面直接执行终端的命令。博友博客描写叙述得非常具体,这里直接转载过来并做些凝视了。


 


目录如下:


一、os 模块


1.1、os模块的exec方法


1.2、os模块的system方法


1.3、os模块popen方法


二、commands模块


2.1、commands.getstatusoutput方法


2.2、commands.getoutput(cmd)只返回输出结果


三、subprocess模块(推荐)


3.1、call(["ls","-l"])


3.2、Popen(["ls","-l"])


3.3、subprocess.call(command, shell=True)


3.4、subprocess.Popen("sh test.sh",shell=True)


四、 众方法的比較以及总结


 


#=====================================================


一、os 模块

1.1、os模块的exec方法


>>> import os 

 

  >>> help (os.execl) 

 

  Help on function execl in module os: 

 

    

 

  execl(file, *args) 

 

  execl(file, *args) 

 

    

 

  Execute the executable file with argument list args, replacing the 

 

  current process.


 


help(os.execl)等能够找到其使用方法说明。


1.2、os模块的system方法


system方法会创建子进程执行外部程序。方法仅仅返回外部程序的执行结果。0表示执行成功。


os模块中的os.system()这个函数来执行shell命令


 


In [10]: os.system("echo \"hello world\"")hello worldOut[10]: 0 

 

    

 

  >>> os.system("echo \"hello world\"") 

 

  hello world 

 

  0 

 

  In [11]: os.system("ls")all_roc_plot.py~ task1_feature_all2.py test.py test.sh ui_without_buy~scrapy_work test test.py~ test.sh~Out[11]: 0>>> os.system("ls") 

 

  README.md create_restore_file.py restore.py statuvpv.py tools.zip 

 

  changeHive.py 

 

  0


 


shell.sh 文件内容如下:


echo "hello world" 

 

  In [12]: os.system("cat test.sh")echo "hello world"Out[12]: 0 

 

  >>> import os 

 

    

 

  >>> os.system("cat test.sh") 

 

  echo "hello world" 

 

  0 

 

  In [13]: os.system("sh test.sh")hello worldOut[13]: 0 

 

    

 

  >>> os.system("sh test.sh") 

 

  hello world 

 

  0


 


如上。一些主要的shell命令,传入os.system()參数里面,便能运行。


只是无法得到命令的返回值。


 


1.3、os模块popen方法


popen方法可以得到shell命令的返回值。os.popen(cmd)后,须要再调用read()或者readlines()这两个命令。输出结果。


 


#这个方法能得到命令执行后的结果是一个字符串,要自行处理才能得到想要的信息。


 


>>> import os 

 

  >>> str = os.popen("ls").read() 

 

  >>> a = str.split("\n") 

 

  >>> for b in a: 

 

  print b 

 

    

 

  >> os.popen("ls").readlines() 

 

  ['0\n', '0119.txt\n', '0703\n', 'a.py\n', 'b.py\n', 'book.json\n', 'character.sh\n', 'data_for_spark_ml\n', 'date1.txt\n', 'f1.log\n'] 

 

    

 

  In [14]: os.popen("ls")Out[14]: <open file 'ls', mode 'r' at 0xb67efd30>


注意。read()或者readlines()后,其每一个元素包括一个回车符\n。


 


二、commands模块


使用commands模块的getoutput方法,这样的方法同popend的差别在于popen返回的是一个文件句柄,而本方法将外部程序的输出结果当作字符串返回。非常多情况下用起来要更方便些。


主要方法:  


*   commands.getstatusoutput(cmd)         返回(status, output) 

 

  *   commands.getoutput(cmd)                   仅仅返回输出结果 

 

  *   commands.getstatus(file)                     返回ls -ld file的运行结果字符串,调用了getoutput。不建议 

 

    

 

  commands模块#可以很方便的取得命令的输出(包括标准和错误输出)和执行状态位


2.1、commands.getstatusoutput方法


import commands 

 

  a,b = commands.getstatusoutput('ls')


a是退出状态


b是输出的结果。


 


>>> import commands 

 

  >>> a,b = commands.getstatusoutput('ls') 

 

  >>> a 

 

  0 

 

  >>> b 

 

  '0\n0119.txt\n0703\na.py\nb.py\nbook.json\ncharacter.sh' 

 

    

 

  commands.getstatusoutput(cmd)返回(status,output) 

 

  而commands.getoutput(cmd)只返回输出结果


 


2.2、commands.getoutput(cmd)只返回输出结果


commands.getstatus(file)返回ls -ld file 的执行结果字符串,调用了getoutput,不建议使用这个方法。


 


>>> import commands 

 

  >>> commands.getstatusoutput('ls') 

 

  (0, '0\n0119.txt\n0703\na.py\nb.py\nbook.json\ncharacter.sh') 

 

    

 

  >>> commands.getoutput("ls") 

 

  '0\n0119.txt\n0703\na.py\nb.py\nbook.json\ncharacter.sh'


三、subprocess模块(推荐)


使用subprocess模块可以创建新的进程,可以与新建进程的输入/输出/错误管道连通,并可以获得新建进程执行的返回状态。使用subprocess模块的目的是替代os.system()、os.popen*()、commands.*等旧的函数或模块。


 


1)、subprocess.call(["some_command","some_argument","another_argument_or_path"]) 

 

  subprocess.call(command,shell=True) 

 

  2)、subprocess.Popen(command,shell=True) 

 

    

 

  subprocess.call(command, shell=True) #会直接打印出结果。 

 

  subprocess.Popen(command, shell=True) 也能够是subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) 这样就能够输出结果了。


 


注意: 如果command不是一个可执行文件,shell=True是不可省略的。shell=True意思是shell下执行command


 


最简单的方法是使用class subprocess.Popen(command,shell=True)。Popen类Popen.stdin,Popen.stdout,Popen.stderr三个实用的属性,能够实现与子进程的通信。


3.1、call(["ls","-l"])


>>> from subprocess import call 

 

  >>> call(["ls","-l"]) 

 

  total 9880 

 

  drwxr-xr-x 2 a6 staff 64 7 3 09:32 0 

 

  -rw-r--r-- 1 a6 staff 17 1 19 15:35 0119.txt 

 

  drwxr-xr-x 10052 a6 staff 321664 7 3 09:38 0703 

 

  -rw-r--r-- 1 a6 staff 59 10 24 2017 a.py0


3.2、Popen(["ls","-l"])


>>> from subprocess import Popen 

 

  >>> Popen(["ls","-l"]) 

 

  <subprocess.Popen object at 0x1050c6210> 

 

  >>> total 9880 

 

  drwxr-xr-x 2 a6 staff 64 7 3 09:32 0 

 

  -rw-r--r-- 1 a6 staff 17 1 19 15:35 0119.txt 

 

  drwxr-xr-x 10052 a6 staff 321664 7 3 09:38 0703


3.3、subprocess.call(command, shell=True)


>>> import subprocess 

 

  >>> return_code = subprocess.call("echo Hello World", shell=True) 

 

  Hello World


3.4、subprocess.Popen("sh test.sh",shell=True)


>>> import subprocess 

 

  >>> subprocess.Popen("sh test.sh",shell=True) 

 

  <subprocess.Popen object at 0x1050c6550> 

 

  >>> hello world


四、 众方法的比較以及总结

4.1. 关于 os.system 


os.system("some_command with args")将命令以及參数传递给你的系统shell。这非常好,由于你能够用这样的方法同一时候执行多个命令而且能够设置管道以及输入输出重定向。比方:


os.system("some_command < input_file | another_command > output_file")


然而,尽管这非常方便,可是你须要手动处理shell字符的转义,比方空格等。此外。这也仅仅能让你执行简单的shell命令并且不能执行外部程序。


4.2. 关于os.popen


使用stream = os.popen("some_command with args")也能做与os.system一样的事。与os.system不同的是os.popen会给你一个像文件的对象从而你能够使用它来訪问哪个程序的标准输入、输出。


并且popen还有三个变种都是在I/O处理上有轻微不同。假如你通过一个字符串传递全部东西。你的命令会传递给shell;假设你通过一个列表传递他们。你不用操心逃避不论什么事。


4.3. 关于subprocess.popen


subprocess模块的Popen类,意图作为os.popen的替代,可是由于其非常全面所以比os.popen要显得略微复杂。使用起来须要学习哦~~。


 


比方你能够使用  print Popen("echo Hello World", stdout=PIPE, shell=True).stdout.read()  来替代  print os.popen("echo Hello World").read()。


可是相比之下它使用一个统一的类包含4中不同的popen函数还是不错的。


4.4. 关于subprocess.call


subprocess模块的call函数。


它基本上就像Popen类并都使用同样的參数,可是它仅仅简单的等待命令完毕并给你返回代码。比方:


>>> import subprocess 

 

  >>> return_code = subprocess.call("echo Hello World", shell=True) 

 

  Hello World


 


參考:



2、 http://zhou123.blog.51cto.com/4355617/1312791