凉城旧巷
Python从入门到自闭,Java从自闭到放弃,数据库从删库到跑路,Linux从rm -rf到完犊子!!!

subprocess模块

一、python执行命令方法

1、os.system()

os.system()的返回值是脚本的退出状态码,0表示成功; 其他均为失败

执行命令出错,并不会影响主进程执行

res = os.system('ls')
print(res)  # 0

res = os.system('dddd')
print(res)  # 32512
print(os.system('ls'))
print(os.system('ddd'))
print(111)

0
32512
111

 

2、subprocess模块

1)subprocess包提供了三个开启子进程的方法:

  • subprocess.call()
  • subprocess.check_call()
  • subprocess.check_output()

2)三种方法区别在于返回结果不同:

  • call() 返回子进程的执行返回码
  • check_call() 返回子进程的执行返回码的处理结果,返回码是0则返回0,否则出错的话会raise CalledProcessError
  • check_output() 返回码是0则返回子进程向stdout输出的结果,否则也raise CalledProcessError

3)传递命令字符串作为参数,可以用以下两种形式

  • 列表形式:['ping','www.baidu.com','-c','3']
  • 字符串形式:"ping www.baidu.com -c 3"

4)在开启子进程的时候,可以加上shell=True的参数来让python开启一个shell,通过shell来解释获得的命令。

  • 一般在windows下运行的程序最好都把shell=True加上,这样才能顺利地执行dos命令
  • linux下似乎不加也没啥关系。因为linux下未指明用shell执行的话会调用/bin/sh来执行,但是dos下系统不会默认用cmd.exe来执行命令,所以要加上shell=True。

5)这三个方法都是对subprocess.Popen方法的一个包装,让父进程挂起等待的,在子进程结束之前,父进程不会继续往下运行

6)subprocess.Popen()方法不会让父进程等待其完成的, 如要父进程等待子进程,必须调用wait()方法

 

二、subprocess.Popen()方法

subprocess.Popen(args, bufsize=-1, executable=None,
                                         stdin=None, stdout=None, stderr=None,
                                         preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
                                         shell=False, cwd=None, env=None, universal_newlines=False,
                                         startupinfo=None, creationflags=0,
                                         restore_signals=True, start_new_session=False,
                                         pass_fds=(), *, encoding=None, errors=None)

"""
常用参数:
      args: 字符串或列表
      stdin, stdout and stderr: None->继承父进程;PIPE->创建管道; 等等

      preexec_fn: (POSIX only) 在创建(fork)和执行(exec)之间执行

      shell: unix相当于在args前面添加"/bin/bash -c";widows下相当于添加"cmd.exe /c"

      cwd: 设置shell执行的工作目录

      env: 设置环境变量,默认为None,默认继承父进程的环境变量

    Attributes:
        stdin, stdout, stderr, pid, returncode
    """

 

1、常用参数详解

  • stdin, stdout and stderr

    输入、输出、错误,既可以输出到PIPE中,也可以输出到文件中,注意PIPE爆满导致卡死,communicate()可解决:https://www.cnblogs.com/linagcheng/p/15352648.html

  • preexec_fn

    详见:https://www.cnblogs.com/linagcheng/p/15597279.html

    接受一个回调函数,并在 fork 之后 exec 之前的间隙中执行它

    应用:执行 os.setsid() 成立一个独立的进程组,通过向进程组发送 SIGTERMSIGKILL来kill subprocess中的所有子孙进程

  • start_new_session

    为True时,新建一个进程组,并以当前进程为master进程,一旦向该进程组发送 SIGTERMSIGKILL,便可kiil subprocess中的所有子孙进程

    功能与preexec_fn=os.setsid()类似

  • shell

    unix相当于在args前面添加/bin/bash -c;widows下相当于添加cmd.exe /c

  • env

    用于指定子进程的环境变量,如果env=None(默认),那么子进程的环境变量将从父进程中继承。如果env!=None,它的值必须是一个映射对象。

  • cwd

    设置shell执行的工作目录
     

三、在一个shell中执行多条命令

方式一:

创建一个shell,通过stdin.write()来不断执行命令

之一每个命令多要用utf-8编码, \n结尾表示模拟回车执行命令

p = subprocess.Popen("/bin/bash", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
p.stdin.write('chmod +x /data/start.sh\n'.encode('utf-8'))
p.stdin.write('cd /data\n'.encode('utf-8'))
p.stdin.write('./start.sh\n'.encode('utf-8'))
p.stdin.close()
p.wait()

方式二:

将多条命令整合到一条中,然后执行

p = subprocess.Popen('chmod +x /data/start.sh && cd /data && ./start.sh', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()

 

四、returncode

None —— 子进程尚未结束;
==0  —— 子进程正常退出;
> 0  —— 子进程异常退出,returncode对应于出错码;
< 0  —— 子进程被信号杀掉了。
posted on 2021-02-05 18:10  凉城旧巷  阅读(893)  评论(0编辑  收藏  举报