Python执行系统命令的方法

2014年7月12日 发表评论 阅读评论

在写python代码的时候,有时会需要调用系统命令执行。这里总结下调用系统命令的方法及各自的特点。

一、os模块函数执行

1、os.system

先看示例:

>>> import os
>>> os.system('ls')
bin  etc  games  include  java  jdk  lib  man  sbin  scripts  share  src
0

注意这里最后会返回一个returncode 零,感觉挺蛋疼的,在utuntu和centos上都会有。另外要注意这里是在交互模式下执行的有输出,如果写在py文件里执行,没有标准输出。

特点: 仅仅在一个子终端运行系统命令,而不能获取命令执行后的返回信息。如果想获取返回的结果,需要结合print 操作,执行流程如下:

system(command) -> exit_status
Execute the command (a string) in a subshell.

2、os.popen

也是os模块下的一个函数,示例如下:

>>> import os
>>> os.popen('ls')
<open file 'ls', mode 'r' at 0x9ed390>
>>> os.popen('ls').readlines()
['binn', 'etcn', 'gamesn', 'includen', 'javan', 'jdkn', 'libn', 'mann', 'sbinn', 'scriptsn', 'sharen', 'srcn']

特点: 该方法不但执行命令还返回执行后的信息对象,好处在于将返回的结果赋于一变量,便于程序的处理。其执行流程如下:

popen(command [, mode='r' [, bufsize]]) -> pipe
Open a pipe to/from a command returning a file object.

需要注意的是,使用os.popen执行命令的参数或者返回中包含了中文文字就会报错(该情况下强烈建议使用subprocess模块),报错信息如下:

Traceback (most recent call last):
  File "./361waytest.py", line 13, in sendFax
    os.popen(cmd)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 46-52: ordinal not inrange(128)

二、subprocess模块函数执行

subprocess模块主要用于替代以下几个模块函数(具体可以参看 官方docs 文档页面 )

os.system
os.spawn*
os.popen*
popen2.*
commands.*

相对应的subprocess 模块里有 call 函数和 popen 函数 。

1、subprocess.call

call 函数的用法如下:

 subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)

可以看出,相对于os模块中的函数,这里可以指定的选项更多。

>>> import subprocess
>>> subprocess.call(["ls", "-l"])
total 40
drwxr-xr-x 2 root root 4096 Oct 25  2013 bin
drwxr-xr-x 2 root root 4096 Jan 24  2013 etc
drwxr-xr-x 2 root root 4096 Jan 24  2013 games
drwxr-xr-x 2 root root 4096 Jan 24  2013 include
lrwxrwxrwx 1 root root    3 Jul  4  2013 java -> jdk
drwxr-xr-x 8 root root 4096 Sep 28  2013 jdk
drwxr-xr-x 3 root root 4096 Jan 24  2013 lib
lrwxrwxrwx 1 root root    9 Jan 24  2013 man -> share/man
drwxr-xr-x 2 root root 4096 May 29 04:01 sbin
drwxr-xr-x 2 root root 4096 May 29 08:19 scripts
drwxr-xr-x 7 root root 4096 Sep 28  2013 share
drwxr-xr-x 2 root root 4096 Jan 24  2013 src
0

交互式模式下,call 也会有returncode 0 输出,不过在py文件里执行时,ruturn的结果并不会将最后的 0 输出。不过在使用call 函数时,需要注意后面的几个参数

Warning:
开启shell=True是危险的(或不安全的)
Using shell=True can be a security hazard. See the warning under Frequently Used Arguments for details.
Note:
尽量不要启用标准输出和标准错误输出需要管道,call有可能会导致子进程死锁。如需管道时,请使用Popen函数
Do not use stdout=PIPE or stderr=PIPE with this function as that can deadlock based on the child process output volume. Use Popen with the communicate() method when you need pipes.

subprocess.call 主要用于替换 os.system ,具体如下:

status = os.system("mycmd" + " myarg")
# becomes
status = subprocess.call("mycmd" + " myarg", shell=True)

2、Popen类函数

sub.process.Popen的用法如下:

subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)

可以看出其支持的参数相当多,下面结合示例看下其用法:

>>> subprocess.Popen('ls')
<subprocess.Popen object at 0x2d96b10>
>>> bin  etc  games  include  java      jdk  lib  man  sbin  scripts  share  src
加参数时
>>> subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
<subprocess.Popen object at 0x2979a90>
>>> p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
>>> for line in p.stdout.readlines():
...     print line
...
bin
etc
games
include
java
jdk
lib
man
sbin
scripts
share
src

subprocess.Popen用于替代 os.popen、os.popen2、os.popen3、os.popen4 ,这里只列举下替代os.open 的用法

pipe = os.popen("cmd", 'r', bufsize)
==>
pipe = Popen("cmd", shell=True, bufsize=bufsize, stdout=PIPE).stdout
pipe = os.popen("cmd", 'w', bufsize)
==>
pipe = Popen("cmd", shell=True, bufsize=bufsize, stdin=PIPE).stdin

其他代替部分可以查看官方文档。

subprocess.call 和 subprocess.Popen 使用上也有区别,由于不是本篇幅的重点,这里不再赘述。

三、使用commands模块

由于commands也在subprocess模块替代的范畴,这里就不再说commands模块的用法,直接上示例:

>>> import commands
>>> dir(commands)
['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'getoutput', 'getstatus', 'getstatusoutput', 'mk2arg', 'mkarg']
>>> commands.getoutput("ls")
'binnetcngamesnincludenjavanjdknlibnmannsbinnscriptsnsharensrc'
>>> commands.getstatusoutput("ls")
(0, 'binnetcngamesnincludenjavanjdknlibnmannsbinnscriptsnsharensrc')




本站的发展离不开您的资助,金额随意,欢迎来赏!

You can donate through PayPal.
My paypal id: itybku@139.com
Paypal page: https://www.paypal.me/361way

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.