在写python脚本的时候,经常需要调用系统命令,常用的python调用系统命令的方法主要有subprocess.call和os.popen。默认情况下subprocess.call的方法结果是返回值,即1或0,而os.popen则是命令运行的结果,可以用readlines(读取所有行,返回数组)或者read(读读取所有行,返回str)来读取。
subprocess类总主要的方法有:
subprocess.call:开启子进程,开启子进程,运行命令,默认结果是返回值,不能try
subprocess.check_call:运行命令,默认结果是返回值,可以try
subprocess.check_out(2.7中才有这个方法) 开启子进程,运行命令,可以获取命令结果,可以try
subprocess.Popen 开启子进程,运行命令,没有返回值,不能try,可以获取命令结果
subprocess.PIPE 初始化stdin,stdout,stderr,表示与子进程通信的标准流
Popen.poll 检查子进程是否结束,并返回returncode
Popen.wait等待子进程是否结束,并返回retrurncode
比如check_call的sample:
1
2
3
4
5
6
7
8
9
10
|
import
subprocess
import
traceback
cmd
=
'hadoop fs -ls hdfs://xxxxx'
try
:
e
=
subprocess.check_call(cmd,shell
=
True
,stdout
=
subprocess.PIPE)
print
"return code is: %s"
%
(
str
(e))
#print stdout.read()
except
Exception,re:
print
"message is:%s"
%
(
str
(re))
traceback.print_exc()
|
分析subprocess的源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
class
CalledProcessError(Exception):
#首先定义了一个exception,用来在check_call和 check_output中raise exception
def
__init__(
self
, returncode, cmd, output
=
None
):
self
.returncode
=
returncode
self
.cmd
=
cmd
self
.output
=
output
def
__str__(
self
):
return
"Command '%s' returned non-zero exit status %d"
%
(
self
.cmd,
self
.returncode)
..........
def
call(
*
popenargs,
*
*
kwargs):
return
Popen(
*
popenargs,
*
*
kwargs).wait()
#call方法调用wait
def
check_call(
*
popenargs,
*
*
kwargs):
retcode
=
call(
*
popenargs,
*
*
kwargs)
#调用call,返回返回值
if
retcode:
cmd
=
kwargs.get(
"args"
)
if
cmd
is
None
:
cmd
=
popenargs[
0
]
raise
CalledProcessError(retcode, cmd)
#可以抛出异常
return
0
def
check_output(
*
popenargs,
*
*
kwargs):
if
'stdout'
in
kwargs:
raise
ValueError(
'stdout argument not allowed, it will be overridden.'
)
process
=
Popen(stdout
=
PIPE,
*
popenargs,
*
*
kwargs)
output, unused_err
=
process.communicate()
#获取标准输出和标准错误输出
retcode
=
process.poll()
#检查子进程是否结束,并返回returncode
if
retcode:
cmd
=
kwargs.get(
"args"
)
if
cmd
is
None
:
cmd
=
popenargs[
0
]
raise
CalledProcessError(retcode, cmd, output
=
output)
return
output
|
可以对上面的代码进行组合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
# -*- coding: utf8 -*-
import
exceptions
import
subprocess
import
traceback
class
CalledCommandError(Exception):
def
__init__(
self
, returncode, cmd, errorlog,output):
self
.returncode
=
returncode
self
.cmd
=
cmd
self
.output
=
output
self
.errorlog
=
errorlog
def
__str__(
self
):
return
"命令运行错误:'%s',返回值: %s,错误信息: %s"
%
(
self
.cmd,
str
(
self
.returncode) ,
self
.errorlog)
def
run_command_all(
*
popenargs,
*
*
kwargs):
allresult
=
{}
cmd
=
popenargs[
0
]
if
'stdout'
in
kwargs
or
'stderr'
in
kwargs :
raise
ValueError(
'标准输出和标准错误输出已经定义,不需设置。'
)
process
=
subprocess.Popen(stdout
=
subprocess.PIPE,shell
=
True
,stderr
=
subprocess.PIPE,
*
popenargs,
*
*
kwargs)
output, unused_err
=
process.communicate()
retcode
=
process.poll()
if
retcode:
#print retcode,cmd,unused_err,output
raise
CalledCommandError(cmd,retcode,errorlog
=
unused_err,output
=
output)
allresult[
'cmd'
]
=
cmd
allresult[
'returncode'
]
=
retcode
allresult[
'errorlog'
]
=
unused_err
allresult[
'outdata'
]
=
output
return
allresult
if
__name__
=
=
'__main__'
:
cmd
=
'hadoop fs -ls xxxx|wc -l'
try
:
e
=
run_command_all(cmd)
print
"ok"
except
Exception,re:
print
(
str
(re))
print
"failed"
traceback.print_exc()
|
本文转自菜菜光 51CTO博客,原文链接:http://blog.51cto.com/caiguangguang/1554549,如需转载请自行联系原作者