python调用shell命令之三大方法

本文介绍了如何使用Python中的os模块、commands模块及subprocess模块来调用Shell命令,包括执行命令、获取命令输出及返回值的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

From : http://write.blog.youkuaiyun.com/postedit?ref=toolbar

preface: 忙于最近的任务,需要用到libsvm的一些命令,如在终端运行Java svm_train train_file model_file. Pythonsubset.py file train_num train_file test_file等命令,但file的准备又是通过python写好的,file需要是libsvm能够接受的格式,故用python写好特征,转为libsvm能够接受的格式,生成file,然后在终端调用训练。故想着直接在python代码里面直接运行终端的命令。博友博客描述得很详细,这里直接转载过来并做些注释了。

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

一、os 模块

1.1.os模块的exec方法簇:

ipython交互界面中:

  1. In [1]: import os  
  2.   
  3. In [2]: os.exec  
  4. os.execl    os.execlp   os.execv    os.execvp     
  5. os.execle   os.execlpe  os.execve   os.execvpe    
  6.   
  7. In [2]: os.execl?  
  8. Type:        function  
  9. String form: <function execl at 0xb73673e4>  
  10. File:        /home/shifeng/anaconda/lib/python2.7/os.py  
  11. Definition:  os.execl(file, *args)  
  12. Docstring:  
  13. execl(file, *args)  
  14.   
  15. Execute the executable file with argument list args, replacing the  
  16. current process.   

os.exec+Tab键智能提示可以看到有8个,help(os.execl)等可以找到其用法说明。

1.2.os模块的system方法

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

  1. In [10]: os.system("echo \"hello world\"")  
  2. hello world  
  3. Out[10]: 0  
  4.   
  5. In [11]: os.system("ls")  
  6. all_roc_plot.py~  task1_feature_all2.py  test.py   test.sh   ui_without_buy~  
  7. scrapy_work   test           test.py~  test.sh~  
  8. Out[11]: 0  
  9.   
  10. In [12]: os.system("cat test.sh")  
  11. echo "hello world"  
  12. Out[12]: 0  
  13.   
  14. In [13]: os.system("sh test.sh")  
  15. hello world  
  16. Out[13]: 0  
如上,一些基本的shell命令,传入os.system()参数里面,便能执行。不过无法得到命令的返回值。

1.3.os模块popen方法

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

  1. In [14]: os.popen("ls")  
  2. Out[14]: <open file 'ls', mode 'r' at 0xb67efd30>  
  3.   
  4. In [15]: os.popen("ls").read()  
  5. Out[15]: 'all_roc_plot.py~\nscrapy_work\ntask1_feature_all2.py\ntest\ntest.py\ntest.py~\ntest.sh\ntest.sh~\nui_without_buy~\n'  
  6.   
  7. In [16]: os.popen("ls").readlines()  
  8. Out[16]:   
  9. ['all_roc_plot.py~\n',  
  10.  'scrapy_work\n',  
  11.  'task1_feature_all2.py\n',  
  12.  'test\n',  
  13.  'test.py\n',  
  14.  'test.py~\n',  
  15.  'test.sh\n',  
  16.  'test.sh~\n',  
  17.  'ui_without_buy~\n']  
  18.   
  19. In [17]: s = os.popen("ls").read()  
  20.   
  21. In [18]: for i in s.split("\n"):  
  22.    ....:     print i  
  23.    ....:       
  24. all_roc_plot.py~  
  25. scrapy_work  
  26. task1_feature_all2.py  
  27. test  
  28. test.py  
  29. test.py~  
  30. test.sh  
  31. test.sh~  
  32. ui_without_buy~  

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

二、commands模块

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

*   commands.getstatusoutput(cmd)         返回(status, output)
*   commands.getoutput(cmd)                   只返回输出结果
*   commands.getstatus(file)                     返回ls -ld file的执行结果字符串,调用了getoutput,不建议使用此方法
  1. In [8]: import commands   
  2.   
  3. In [9]: commands.getoutput("ls")  
  4. Out[9]: 'all_roc_plot.py~\nscrapy_work\ntask1_feature_all2.py\ntest\ntest.py\ntest.py~\ntest.sh\ntest.sh~\nui_without_buy~'  
  5.   
  6. In [10]: commands.getstatusoutput("ls")  
  7. Out[10]:   
  8. (0,  
  9.  'all_roc_plot.py~\nscrapy_work\ntask1_feature_all2.py\ntest\ntest.py\ntest.py~\ntest.sh\ntest.sh~\nui_without_buy~')  

三、subprocess模块

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

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

subprocess.call(command,shell=True)

3.2.subprocess.Popen(command,shell=True)
如果command不是一个可执行文件,shell=True不可省。
使用subprocess模块可以创建新的进程,可以与新建进程的输入/输出/错误管道连通,并可以获得新建进程执行的返回状态。使用subprocess模块的目的是替代os.system()、os.popen*()、commands.*等旧的函数或模块。
最简单的方法是使用classsubprocess.Popen(command,shell=True)。Popen类Popen.stdin,Popen.stdout,Popen.stderr三个有用的属性,可以实现与子进程的通信。
  1. In [11]: from subprocess import  call  
  2.   
  3. In [12]: call(["ls","-l"])  
  4. 总用量 40  
  5. -rw-rw-r-- 1 shifeng shifeng  3266  5月  3 14:14 all_roc_plot.py~  
  6. drwxrwxr-x 6 shifeng shifeng  4096  6月 18 16:59 scrapy_work  
  7. -rw-rw-r-- 1 shifeng shifeng 12786  6月 10 10:20 task1_feature_all2.py  
  8. drwxrwxr-x 2 shifeng shifeng  4096  6月  8 11:36 test  
  9. -rw-rw-r-- 1 shifeng shifeng  3649  6月 19 10:21 test.py  
  10. -rw-rw-r-- 1 shifeng shifeng   255  6月 11 21:21 test.py~  
  11. -rw-rw-r-- 1 shifeng shifeng    19  6月 25 19:49 test.sh  
  12. -rw-rw-r-- 1 shifeng shifeng     0  6月 25 19:49 test.sh~  
  13. -rw-rw-r-- 1 shifeng shifeng     0  4月  8 22:15 ui_without_buy~  
  14. Out[12]: 0  
  15.   
  16. In [13]: from subprocess import  Popen  
  17.   
  18. In [14]: Popen(["ls","-l"])  
  19. Out[14]: <subprocess.Popen at 0xb67c91ac>  
  20.   
  21. In [15]: 总用量 40  
  22. -rw-rw-r-- 1 shifeng shifeng  3266  5月  3 14:14 all_roc_plot.py~  
  23. drwxrwxr-x 6 shifeng shifeng  4096  6月 18 16:59 scrapy_work  
  24. -rw-rw-r-- 1 shifeng shifeng 12786  6月 10 10:20 task1_feature_all2.py  
  25. drwxrwxr-x 2 shifeng shifeng  4096  6月  8 11:36 test  
  26. -rw-rw-r-- 1 shifeng shifeng  3649  6月 19 10:21 test.py  
  27. -rw-rw-r-- 1 shifeng shifeng   255  6月 11 21:21 test.py~  
  28. -rw-rw-r-- 1 shifeng shifeng    19  6月 25 19:49 test.sh  
  29. -rw-rw-r-- 1 shifeng shifeng     0  6月 25 19:49 test.sh~  
  30. -rw-rw-r-- 1 shifeng shifeng     0  4月  8 22:15 ui_without_buy~  

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

2、subprocess.Popen(command, shell=True) 也可以是subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) 这样就可以输出结果了。如果command不是一个可执行文件,shell=True是不可省略的。shell=True意思是shell下执行command。

#========================以下转载============

4. 众方法的比较以及总结

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类并都使用相同的参数,但是它只简单的等待命令完成并给你返回代码。比如:
return_code = subprocess.call("echo Hello World", shell=True)

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

参考:

1.博友博客:http://blog.youkuaiyun.com/longerzone/article/details/17889969

2.博友博客:http://zhou123.blog.51cto.com/4355617/1312791

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值