Python常用模块-subprocess系统交互
Python常用模块-subprocess系统交互
http://www.cnblogs.com/alex3714/articles/5161349.html
https://www.cnblogs.com/iznogoud/articles/5607931.html
运行python的时候,我们都是在创建并运行一个进程。像Linux进程那样,一个进程可以fork一个子进程,并让这个子进程exec另外一个程序。在Python中,我们通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序。
subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用。另外subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。
标准例子
import subprocess subprocess.run("ls ") subprocess.run("ls -l") subprocess.run("ls -l",shell=True) >>> import subprocess >>> subprocess.run("ls -l") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/python3.6.0/lib/python3.6/subprocess.py", line 403, in run with Popen(*popenargs, **kwargs) as process: File "/usr/local/python3.6.0/lib/python3.6/subprocess.py", line 707, in __init__ restore_signals, start_new_session) File "/usr/local/python3.6.0/lib/python3.6/subprocess.py", line 1326, in _execute_child raise child_exception_type(errno_num, err_msg) FileNotFoundError: [Errno 2] No such file or directory: 'ls -l' >>> subprocess.run("ls -l",shell=True) total 32 -rw-rw-r-- 1 admin admin 21 Jan 18 13:52 a.pw drwxr-xr-x 7 admin admin 4096 Jul 10 00:21 data_bak lrwxrwxrwx 1 admin admin 21 Jan 19 09:48 falcon -> /data/workdir/falcon/ -rwxr-xr-x 1 admin admin 167 Jan 18 13:52 iplist lrwxrwxrwx 1 admin admin 19 Jun 27 10:03 jira -> /data/workdir/jira/ -rwxrwxrwx 1 admin admin 119 Jan 18 13:52 kill.sh -rw-rw-r-- 1 admin admin 1011 Jan 18 13:52 list lrwxrwxrwx 1 admin admin 22 Nov 10 2015 scripts -> /data/workdir/scripts/ -rw------- 1 admin admin 0 Jan 17 15:14 sent lrwxrwxrwx 1 admin admin 19 Jan 18 10:29 soft -> /data/workdir/soft/ -rwxr-xr-x 1 admin admin 23 Jan 18 13:52 tianlala.sh lrwxrwxrwx 1 admin admin 29 Jan 18 10:29 tomcat_jenkins -> /data/workdir/tomcat_jenkins/ drwxrwxr-x 4 admin admin 4096 Jun 13 16:31 wangxu lrwxrwxrwx 1 admin admin 24 Nov 9 2015 webserver -> /data/workdir/webserver/ -rwxr-xr-x 1 admin admin 17 Jan 18 13:52 yuanzheng CompletedProcess(args='ls -l', returncode=0) >>>
调用subprocess.run(...)是推荐的常用方法,在大多数情况下能满足需求,但如果你可能需要进行一些复杂的与系统的交互的话,你还可以用subprocess.Popen(),语法如下:
import subprocess ret = subprocess.Popen("du -sh",shell=True,stdout=subprocess.PIPE) print(ret.stdout.read())
常用函数
https://www.cnblogs.com/sunshine-1/p/7290468.html
函数 |
描述 |
subprocess.run() |
Python 3.5中新增的函数。执行指定的命令,等待命令执行完成后返回一个包含执行结果的CompletedProcess类的实例。 |
subprocess.call() |
执行指定的命令,返回命令执行状态,其功能类似于os.system(cmd)。 |
subprocess.check_call() |
Python 2.5中新增的函数。 执行指定的命令,如果执行成功则返回状态码,否则抛出异常。其功能等价于subprocess.run(..., check=True)。 |
subprocess.check_output() |
Python 2.7中新增的的函数。执行指定的命令,如果执行状态码为0则返回命令执行结果,否则抛出异常。 |
subprocess.getoutput(cmd) |
接收字符串格式的命令,执行命令并返回执行结果,其功能类似于os.popen(cmd).read()和commands.getoutput(cmd)。 |
subprocess.getstatusoutput(cmd) |
执行cmd命令,返回一个元组(命令执行状态, 命令执行结果输出),其功能类似于commands.getstatusoutput()。 |
说明:
- 在Python 3.5之后的版本中,官方文档中提倡通过subprocess.run()函数替代其他函数来使用subproccess模块的功能;
- 在Python 3.5之前的版本中,我们可以通过subprocess.call(),subprocess.getoutput()等上面列出的其他函数来使用subprocess模块的功能;
- subprocess.run()、subprocess.call()、subprocess.check_call()和subprocess.check_output()都是通过对subprocess.Popen的封装来实现的高级函数,因此如果我们需要更复杂功能时,可以通过subprocess.Popen来完成。
- subprocess.getoutput()和subprocess.getstatusoutput()函数是来自Python 2.x的commands模块的两个遗留函数。它们隐式的调用系统shell,并且不保证其他函数所具有的安全性和异常处理的一致性。另外,它们从Python 3.3.4开始才支持Windows平台。
可用参数
- 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()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等
终端输入的命令分为两种:
- 输入即可得到输出,如:ifconfig
- 输入进行某环境,依赖再输入,如:python
PIPI管道样例
import subprocess obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True) # universal_newlines=True),否则会报TypeError: a bytes-like object is required, not 'str‘错误 obj.stdin.write("print('1')\n") obj.stdin.write("print('2')\n") obj.stdin.write("print('3')\n") obj.stdin.write("print('4')\n") out_error_list = obj.communicate(timeout=10) print(out_error_list)
>>> import subprocess
>>>
... obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True)
>>> obj.stdin.write("print('1')\n")
11
>>> obj.stdin.write("print('2')\n")
11
>>> obj.stdin.write("print('3')\n")
11
>>> obj.stdin.write("print('4')\n")
11
>>> out_error_list = obj.communicate(timeout=10)
>>> print(out_error_list)
('1\n2\n3\n4\n', '')
>>>
import subprocess m = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) m.stdin.write("print('hello')\n") m.stdin.write("print('hello word')") m.stdin.close() m_out = m.stdout.read() m.stdout.close() m_error = m.stderr.read() m.stderr.close() print(m_out) print(m_error)
>>> m = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
>>> m.stdin.write("print('hello')\n")
15
>>> m.stdin.write("print('hello word')")
19
>>> m.stdin.close()
>>> m_out = m.stdout.read()
>>> m.stdout.close()
>>> m_error = m.stderr.read()
>>> m.stderr.close()
>>> print(m_out)
hello
hello word
>>> print(m_error)
>>>
subprocess实现sudo 自动输入密码
import subprocess def mypass(): mypass = '' #or get the password from anywhere return mypass echo = subprocess.Popen(['echo',mypass()],stdout=subprocess.PIPE, ) sudo = subprocess.Popen(['sudo','-S','iptables','-L'], stdin=echo.stdout, stdout=subprocess.PIPE, ) end_of_pipe = sudo.stdout print("Password ok \n Iptables Chains %s" % end_of_pipe.read())
>>> import subprocess
>>>
... def mypass():
... mypass = '' #or get the password from anywhere
... return mypass
...
... echo = subprocess.Popen(['echo',mypass()],stdout=subprocess.PIPE,
File "<stdin>", line 6
echo = subprocess.Popen(['echo',mypass()],stdout=subprocess.PIPE,
^
SyntaxError: invalid syntax
>>> )
File "<stdin>", line 1
)
^
IndentationError: unexpected indent
>>>
... sudo = subprocess.Popen(['sudo','-S','iptables','-L'],
... stdin=echo.stdout,
... stdout=subprocess.PIPE,
... )
>>>
... end_of_pipe = sudo.stdout
>>>
... print("Password ok \n Iptables Chains %s" % end_of_pipe.read())
Password ok
Iptables Chains b'Chain INPUT (policy ACCEPT)\ntarget prot opt source destination \n\nChain FORWARD (policy ACCEPT)\ntarget prot opt source destination \n\nChain OUTPUT (policy ACCEPT)\ntarget prot opt source destination \n'
>>>