python subprocess

  运行python的时候,我们都是在创建并运行一个进程。像Linux进程那样,一个进程可以fork一个子进程,并让这个子进程exec另外一个程序。在Python中,我们通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序。
  subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用。另外subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。

 

call(*popenargs, **kwargs): 执行命令,返回状态码

>>> import subprocess
>>> ret = subprocess.call(["ls", "-l"])
total 216
-rw-r--r-- 1 root root   297 May  5 21:23 class.py
-rw-r--r-- 1 root root   330 May  4 10:33 fenye.py
-rw-r--r-- 1 root root   173 May  4 07:24 obj.py
>>> ret = subprocess.call("ls -l")   #默认shell=False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/subprocess.py", line 524, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.7/subprocess.py", line 1308, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
>>> ret = subprocess.call("ls -l", shell=True)   #shell=True不会报错
total 216
-rw-r--r-- 1 root root   297 May  5 21:23 class.py
-rw-r--r-- 1 root root   330 May  4 10:33 fenye.py
-rw-r--r-- 1 root root   173 May  4 07:24 obj.py
>>> print(ret)
0

 

check_call(*popenargs, **kwargs): 执行命令,如果执行状态码是 0 ,则返回0,否则抛异常

>>> ret = subprocess.call(["cd", "A"])
/usr/bin/cd: line 2: cd: A: No such file or directory
>>> ret = subprocess.check_call(["cd", "A"])
/usr/bin/cd: line 2: cd: A: No such file or directory
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/subprocess.py", line 542, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['cd', 'A']' returned non-zero exit status 1

 

check_output(*popenargs, **kwargs):执行命令,如果状态码是 0 ,则返回执行结果,否则抛异常

>>> ret = subprocess.check_output(["ls", "-l"])
>>> print(ret)
total 216
-rw-r--r-- 1 root root   297 May  5 21:23 class.py
-rw-r--r-- 1 root root   330 May  4 10:33 fenye.py
-rw-r--r-- 1 root root   173 May  4 07:24 obj.py
>>> ret = subprocess.check_output(["lsa", "-l"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/subprocess.py", line 568, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
  File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.7/subprocess.py", line 1308, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

 

subprocess.Popen(...) 用于执行复杂的系统命令

参数:

    • args:shell命令,可以是字符串或者序列类型(如:list,元组)
    • bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
    • stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
    • preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
    • close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。
      所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
    • shell:同上
    • cwd:用于设置子进程的当前目录
    • env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
    • universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
    • startupinfo与createionflags只在windows下有效将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等 
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
>>> obj.stdin.write("print('hello')\n")
>>> obj.stdin.write("print('hello word')")
>>> obj.stdin.close()
>>> cmd_out = obj.stdout.read()
>>> obj.stdout.close()
>>> cmd_error = obj.stderr.read()
>>> obj.stderr.close()
>>> print(cmd_out)
hello
hello word

>>> print(cmd_error)

或者

>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> obj.stdin.write("print('hello word')")
>>> out_error_list = obj.communicate()
>>> print(out_error_list)
('hello word\n', '')

管道(shell中的|)

[root@Python ~]# ls -l | wc -l
18
>>> p1=subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
>>> p2=subprocess.Popen(["wc","-l"], stdin=p1.stdout,stdout=subprocess.PIPE)
>>> out=p2.communicate()
>>> print(out)
(b'18\n', None)

上面实例其执行过程:

child1.stdout-->subprocess.PIPE

child2.stdin<--subprocess.PIPE

child2.stdout-->subprocess.PIPE

需要注意的是:communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成

posted on 2016-06-22 17:27  逸秋  阅读(2113)  评论(0编辑  收藏  举报

导航