• Python subprocess


    # subprocess - Subprocesses with accessible I/O streams

    This module allows you to spawn processes, connect to their
    input/output/error pipes, and obtain their return codes.

    run(...): Runs a command, waits for it to complete, then returns aCompletedProcess instance.

    Popen(...): A class for flexibly executing a command in a new process.

    subprocess模块主要用于创建子进程,并连接它们的输入、输出和错误管道,获取它们的返回状态。通俗地说就是通过这个模块,你可以在Python的代码里执行操作系统级别的命令,比如“ipconfig”、“du -sh”等等。subprocess模块替代了一些老的模块和函数,比如:os.system,os.spawn*

    subprocess.Popen 类

    通过调用:

    subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, 
    cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)

    创建并返回一个子进程,并在这个进程中执行指定的程序。

      实例化 Popen 可以通过许多参数详细定制子进程的环境,但是只有一个参数是必须的,即位置参数 args .

    参数介绍:

    • args:要执行的命令或可执行文件的路径。一个由字符串组成的序列(通常是列表),列表的第一个元素是可执行程序的路径,剩下的是传给这个程序的参数,如果没有要传给这个程序的参数,args 参数可以仅仅是一个字符串。
    • bufsize:控制 stdinstdoutstderr 等参数指定的文件的缓冲,和打开文件的 open()函数中的参数 bufsize 含义相同。
    • executable:如果这个参数不是 None,将替代参数 args 作为可执行程序;
    • stdin:指定子进程的标准输入;
    • stdout:指定子进程的标准输出;
    • stderr:指定子进程的标准错误输出;

      对于 stdin, stdout 和 stderr 而言,如果他们是 None(默认情况),那么子进程使用和父进程相同的标准流文件。

      父进程如果想要和子进程通过 communicate() 方法通信,对应的参数必须是 subprocess.PIPE(见下文例4);

      当然 stdin, stdout 和 stderr 也可以是已经打开的 file 对象,前提是以合理的方式打开,比如 stdin 对应的文件必须要可读等。 

    • preexec_fn:默认是None,否则必须是一个函数或者可调用对象,在子进程中首先执行这个函数,然后再去执行为子进程指定的程序或Shell。
    • close_fds:布尔型变量,为 True 时,在子进程执行前强制关闭所有除 stdin,stdout和stderr外的文件;
    • shell:布尔型变量,明确要求使用shell运行程序,与参数 executable 一同指定子进程运行在什么 Shell 中——如果executable=None 而 shell=True,则使用 /bin/sh 来执行 args 指定的程序;也就是说,Python首先起一个shell,再用这个shell来解释指定运行的命令。
    • cwd:代表路径的字符串,指定子进程运行的工作目录,要求这个目录必须存在;
    • env:字典,键和值都是为子进程定义环境变量的字符串;
    • universal_newline:布尔型变量,为 True 时,stdout 和 stderr 以通用换行(universal newline)模式打开,
    • startupinfo:见下一个参数;
    • creationfalgs:最后这两个参数是Windows中才有的参数,传递给Win32的CreateProcess API调用。

    同 Linux 中创建子进程类似,父进程创建完子进程后,并不会自动等待子进程执行,父进程在子进程之前推出将导致子进程成为孤儿进程,孤儿进程统一由 init 进程接管,负责其终止后的回收工作。

      如果父进程在子进程之后终止,但子进程终止时父进程没有进行最后的回收工作,子进程残留的数据结构称为僵尸进程。大量僵尸进程将耗费系统资源,因此父进程及时等待和回收子进程是必要的,除非能够确认自己比子进程先终止,从而将回收工作过渡给 init 进程。

      这个等待和回收子进程的操作就是wait()函数

    args可以是字符串也可是是逗号分隔的字符串列表;

    在Linux环境下,当args是个字符串时,必须指定shell=True。成功执行后,返回一个subprocess.Popen对象

    当args是一个['du', '-sh']列表,并且shell=True的时候,参数被忽略了,只执行不带参数的‘du’命令。

    创建一个子进程,然后执行一个简单的命令

    >>> import subprocess

    没有使用标准输出管道

    p = subprocess.Popen(['ls', '-l'],shell=True)

    >>> p = subprocess.Popen('ls -l',shell=True)
    >>> total 10144
    -rw-------. 1 root root 1338 Jul 24 17:56 anaconda-ks.cfg
    -rw-r--r--. 1 root root 141 Aug 21 11:15 dastudiodb.properties
    -rw-r--r--. 1 root root 160 Aug 3 17:12 hostname.txt
    -rw-r--r--. 1 root root 271 Aug 3 17:12 hosts_linux.sh
    -rw-r--r--. 1 root root 9520728 Aug 13 16:32 node_exporter-1.0.1.linux-amd 64.tar.gz
    drwxr-xr-x. 2 root root 6 Jul 27 09:57 perl5
    drwxr-xr-x. 2 root root 24 Sep 25 15:30 pip
    drwxr-xr-x. 2 root root 25 Sep 17 16:11 prestoadmin
    -rw-r--r--. 1 root root 827795 Sep 27 13:49 prestoadmindir.tar.gz
    -rw-r--r--. 1 root root 852 Aug 3 17:12 ssh_config.sh
    -rw-r--r--. 1 root root 12 Aug 5 09:49 suhadoop.sh
    -rw-r--r--. 1 root root 23 Sep 29 14:07 testfile.txt
    -rw-r--r--. 1 root root 1063 Aug 5 10:00 zookeeper.out

    使用标准输出管道

    p = subprocess.Popen('ls -l',stdout=subprocess.PIPE,shell=True)

    >>> p = subprocess.Popen('ls -l',stdout=subprocess.PIPE,shell=True)
    >>> print(p.stdout.read().decode("utf-8"))
    total 10144
    -rw-------. 1 root root 1338 Jul 24 17:56 anaconda-ks.cfg
    -rw-r--r--. 1 root root 141 Aug 21 11:15 dastudiodb.properties
    -rw-r--r--. 1 root root 160 Aug 3 17:12 hostname.txt
    -rw-r--r--. 1 root root 271 Aug 3 17:12 hosts_linux.sh
    -rw-r--r--. 1 root root 9520728 Aug 13 16:32 node_exporter-1.0.1.linux-amd 64.tar.gz
    drwxr-xr-x. 2 root root 6 Jul 27 09:57 perl5
    drwxr-xr-x. 2 root root 24 Sep 25 15:30 pip
    drwxr-xr-x. 2 root root 25 Sep 17 16:11 prestoadmin
    -rw-r--r--. 1 root root 827795 Sep 27 13:49 prestoadmindir.tar.gz
    -rw-r--r--. 1 root root 852 Aug 3 17:12 ssh_config.sh
    -rw-r--r--. 1 root root 12 Aug 5 09:49 suhadoop.sh
    -rw-r--r--. 1 root root 23 Sep 29 14:07 testfile.txt
    -rw-r--r--. 1 root root 1063 Aug 5 10:00 zookeeper.out

     

    ret = subprocess.Popen("ls",stdout=subprocess.PIPE,shell=True)

    print(ret.stdout.read().decode("utf-8"))

    anaconda-ks.cfg
    dastudiodb.properties
    hostname.txt
    hosts_linux.sh
    node_exporter-1.0.1.linux-amd64.tar.gz
    perl5
    pip
    prestoadmin
    prestoadmindir.tar.gz
    ssh_config.sh
    suhadoop.sh
    testfile.txt
    zookeeper.out

    Popen 对象的方法

    p.poll()
    检查子进程  p 是否已经终止,返回 p.returncode 属性
    p.wait()

     等待子进程 p 终止,返回 p.returncode 属性;

      注意:

        wait() 立即阻塞父进程,直到子进程结束!

    p.communicate(input=None)

    和子进程 p 交流,将参数 input (字符串)中的数据发送到子进程的 stdin,同时从子进程的 stdout 和 stderr 读取数据,直到EOF。

      返回值:

        二元组 (stdoutdata, stderrdata) 分别表示从标准出和标准错误中读出的数据。

      父进程调用 p.communicate() 和子进程通信有以下限制:

      (1) 只能通过管道和子进程通信,也就是说,只有调用 Popen() 创建子进程的时候参数 stdin=subprocess.PIPE,才能通过 p.communicate(input) 向子进程的 stdin 发送数据;只有参数 stout 和 stderr 也都为 subprocess.PIPE ,才能通过p.communicate() 从子进程接收数据,否则接收到的二元组中,对应的位置是None。

      (2)父进程从子进程读到的数据缓存在内存中,因此commucate()不适合与子进程交换过大的数据。

      注意:

        communicate() 立即阻塞父进程,直到子进程结束!

    p.send_signal(signal)
    向子进程发送信号 signal
    p.terminate()
    终止子进程 p ,等于向子进程发送 SIGTERM 信号;
    p.kill()

       杀死子进程 p ,等于向子进程发送 SIGKILL 信号;

    subprocess.PIPE
    调用本模块提供的若干函数时,作为 std* 参数的值,为标准流文件打开一个管道。
    使用管道连接标准流文件

    >>> import subprocess
    >>> child1 = subprocess.Popen(['ls','-l'],stdout=subprocess.PIPE)
    >>> child2 = subprocess.Popen(['wc','-l'],stdin=child1.stdout,stdout=subprocess.PIPE)
    >>> out = child2.communicate()
    >>> child1.wait()
    0
    >>> child2.wait()
    0
    >>> print(out)
    (b'14 ', None)

    这里将子进程 child1 的标准输出作为子进程 child2 的标准输入,父进程通过 communicate() 读取 child2 的标准输出后打印。

    subprocess.STDOUT
    调用本模块提供的若干函数时,作为 stderr 参数的值,将子进程的标准错误输出打印到标准输出。

    https://www.cnblogs.com/security-darren/p/4733368.html

    https://www.liujiangblog.com/course/python/55

  • 相关阅读:
    Docker 私有仓库搭建
    事务提交与不同数据库的自增方式
    多环境切换&&注解方式&&增删改返回值问题
    查询缓存&&逆向工程
    Mybatis整合Log4j、延迟加载
    关联查询
    MyBatis实现动态SQL
    输出参数resultType
    MyBatis调用存储过程执行CRUD
    两种取值符号的异同
  • 原文地址:https://www.cnblogs.com/songyuejie/p/13749940.html
Copyright © 2020-2023  润新知