一. 最近subprocess使用背景和介绍
因为最近领导要求,在Python端调用大数据的shell脚本,所以需要用到Python来执行shell脚本, 因此需要查看下subprocess模块文档。
根据官网文档描述:subprocess模块用于创建子进程, 这个模块用于替换旧版本中的一些模块, 如:os.system,
os.spawn*, os.popen*, os.popen*, popen2.*, commands.*, subprocess允许你能创建很多子进程, 创建的时候能能指定子进程和子进程的输入、输出、错误输出管道, 执行后能获取输出结果和执行状态。
二. subprocess模块的常用方法用法介绍
subprocess.run() --> python3.5中新增的函数, 执行指定的命令, 等待命令执行完成后返回一个包含执行结果的 CompletedProcess类的实例。
subprocess.call(): --> 执行指定的命令, 返回命令执行状态, 功能类似羽os.system(cmd)
subprocess.check_call(): --> python2.5中新增的函数, 执行指定的命令, 如果执行成功则返回状态码, 否则抛出异常。
【Tips】: 在python3.5之后的版本中, 官方文档中提倡通过subprocess.run()函数替代其他函数来使用subprocess模块的功能。在python3.5之前的版本中, 我们可以通过subprocess.call()来使用subprocess模块的功能。subprocess.run(), subprocess.call(), subprocess.check_call()都是通过对subprocess.Popen的封装来实现的高级函数。
三. 这几个函数的定义以及参数
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, universal_newlines=False)
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
参数说明:
args: 要执行的shell命令, 默认应该是一个字符串序列, 如['ls', '-l'], 也可以是一个字符串如: 'ls -l', 但是此时需要把shell参数的值置为True。
shell=True参数会让subprocess.call接受字符串类型的变量作为命令, 并调用shell去执行这个字符串, 当shell=False时, subprocess.call只接受数组变量作为命令, 并将数组的第一个元素作为命令, 剩下的全部作为该命令的参数。官方不推荐使用shell=True。
案例:
四. subprocess.CompletedProcess类介绍
subprocess.run()函数是python3.5中新增的一个高级函数, 其返回值是一个subprocess.CompleteProcess类的实例, 它表示的是一个已结束进程的状态信息。 包含属性如下:
args --> 用于加载该进程的参数, 这可能是一个列表或一个字符串
退出状态码0表示进程成功运行了, 一个负值-N表示这个子进程被信号N终止了。
五. subprocess.Popen介绍
class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False,
startup_info=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=())
subprocess.Popen类的实例的一些方法:
方法 | 描述 |
Popen.poll() | 用于检查子进程是否已经执行结束, 没结束返回None, 结束后返回状态码 |
Popen.wait(timeout=None) | 等待子进程结束, 并返回状态码, 如果在timeout指定的秒数之后进程还没有结束, 将会抛出一个TimeoutExpired异常 |
Poen.communicate(input=None, timeout=None) | 该方法可用来与进程进行交互, 比如发送数据到stdin, 从stdout和stderr读取数据, 直到到达文件末尾 |
Popen.send_signal(signal) | 发送指定的信号给这个子进程 |
Popen.terminate() | 停止该子进程 |
Popen.kill() | 杀死该子进程 |
六. 在服务器上实际应用
封装一个subprocess.Popen的方法