zoukankan      html  css  js  c++  java
  • python之subprocess

    官网介绍:https://docs.python.org/3/library/subprocess.html

    Popen():
    [root@oracle scripts]# cat sub_popen.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.Popen(['ls','-l'],shell=True)
    print(type(child))
    print('parent')
    [root@oracle scripts]# python sub_popen.py 
    <class 'subprocess.Popen'>
    parent
    stu_subprocess.py  sub_popen.py
    
    如果将不添加shell,使用默认的:
    [root@oracle scripts]# cat sub_popen.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.Popen(['ls','-l'],shell=False)      shell参数默认为False
    print(type(child))
    print('parent')
    [root@oracle scripts]# python sub_popen.py 
    <class 'subprocess.Popen'>
    parent
    total 8
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 136 Aug 21 15:41 sub_popen.py
    
    Popen不会阻塞父进程运行,Popen启动新的进程与父进程并行执行,默认父进程不等待新进程结束。
    [root@oracle scripts]# cat test_subprocess.py
    #!/usr/bin/python
    #coding=utf8
     
    def TestPopen():
    import subprocess
    p = subprocess.Popen(['ls','-l'],shell=True)
    for i in range(5):
    print("other things")
     
    print(TestPopen())
    [root@oracle scripts]# python test_subprocess.py
    other things
    other things
    other things
    other things
    other things
    None
    stu_subprocess.py sub_call.py sub_check_output.py sub_popen.py sub_run.py test_subprocess.py
     
    [root@oracle scripts]# cat test_subprocess1.py
    #!/usr/bin/python
    #coding=utf8
     
    wait(): 阻塞父进程,等待子进程运行结束再继续运行父进程
    def TestWait():
    import subprocess
    import datetime
    print(datetime.datetime.now())
    p = subprocess.Popen('sleep 10',shell=True)
    p.wait() wait()阻塞了父进程的运行,等待子进程运行完成后才继续运行父进程
    print(p.returncode)
    print(datetime.datetime.now())
     
    TestWait()
    [root@oracle scripts]# python test_subprocess1.py
    2017-08-21 16:49:15.061676
    0 当子进程运行完成结束后,返回code为0
    2017-08-21 16:49:25.066657
     
    poll():判断子进程是否结束
    [root@oracle scripts]# cat test_subprocess2.py
    #!/usr/bin/python
    #coding=utf8
     
    def TestWait():
    import subprocess
    import datetime,time
    print(datetime.datetime.now())
    p = subprocess.Popen('sleep 10',shell=True) 子进程要睡眠10秒
    t = 1
    while (t <= 5):
    time.sleep(1)
    p.poll() 执行判断子进程,这里花了5秒
    print(p.returncode)
    t = t + 1
    print(datetime.datetime.now())
     
    TestWait()
    [root@oracle scripts]# python test_subprocess2.py
    2017-08-21 16:56:33.672417
    None
    None
    None
    None
    None
    2017-08-21 16:56:38.684795
     
    kill()或者terminate(): 杀掉子进程
    [root@oracle scripts]# cat test_subprocess3.py
    #!/usr/bin/python
    #coding=utf8
     
    def TestKillAndTerminate():
    import subprocess
    import datetime,time
    print(datetime.datetime.now())
    p = subprocess.Popen('sleep 10',shell=True)
    t = 1
    while (t <= 5):
    time.sleep(1)
    t = t + 1
    p.kill()
    print(datetime.datetime.now())
     
    TestKillAndTerminate()
    [root@oracle scripts]# python test_subprocess3.py
    2017-08-21 17:03:16.315531
    2017-08-21 17:03:21.329266
    可以看见子进程只运行了5秒
    [root@oracle scripts]# cat sub_popen.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.Popen(['ls','-l'],shell=False)
    child.wait()               阻塞父进程,直到子进程运行完成
    print(type(child))
    print('parent')
    [root@oracle scripts]# python sub_popen.py 
    total 12
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 135 Aug 21 15:47 sub_call.py
    -rw-r--r-- 1 root root 149 Aug 21 15:47 sub_popen.py
    <class 'subprocess.Popen'>
    parent
    可以看出先运行的子进程,最后才是父进程,等待子进程运行后,再运行父进程
    除了wait()之外还有如下:
    child.poll() # 检查子进程状态
    child.kill() # 终止子进程
    child.send_signal() # 向子进程发送信号
    child.terminate() # 终止子进程
    子进程的PID存储在child.pid
    子进程的标准输入、标准输出和标准错误如下属性分别表示:
    child.stdin
    child.stdout
    child.stderr
    
    subprocess.PIPE实际上为文本流提供一个缓存区。child的stdout将文本输出到缓存区,然后打印出缓存区的内容:
    [root@oracle scripts]# cat sub_popen.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.Popen(['ls','-l'],shell=False,stdout=subprocess.PIPE)
    print(child.stdout.read().decode('utf-8'))      打印缓存区内容,由于是bytes格式,所以转码
    print('parent')
    [root@oracle scripts]# python sub_popen.py 
    total 16
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py
    -rw-r--r-- 1 root root 183 Aug 21 16:07 sub_popen.py
    -rw-r--r-- 1 root root 147 Aug 21 15:56 sub_run.py
    
    parent
    
    communicate()
    Popen.communicate(input=None):与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。
    [root@oracle scripts]# cat sub_popen.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.Popen(['ls','-l'],shell=False,stdout=subprocess.PIPE)
    #print(child.stdout.read().decode('utf-8'))
    print(child.communicate())          返回的是标准输出,标准错误输出的tuple
    print('parent')
    [root@oracle scripts]# python sub_popen.py 
    (b'total 16
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py
    -rw-r--r-- 1 root root 211 Aug 21 16:11 sub_popen.py
    -rw-r--r-- 1 root root 147 Aug 21 15:56 sub_run.py
    ', None)    NONE就是标准错误输出结果
    parent
    可以看见先输出的子进程内容,然后才是父进程,communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成
    [root@oracle scripts]# cat sub_popen.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child1 = subprocess.Popen(['cat','/etc/passwd'],shell=False,stdout=subprocess.PIPE)
    child2 = subprocess.Popen(['grep','0:0'],stdin=child1.stdout, stdout=subprocess.PIPE)
    #  subprocess.PIPE实际上为文本流提供一个缓存区。child1的stdout将文本输出到缓存区,随后child2的stdin从该PIPE中将文本读取走。child2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。
    out,err = child2.communicate()   因为communicate()返回的是一个元祖
    print(out)     纸打印出标准输出内容
    print('parent')
    [root@oracle scripts]# python sub_popen.py 
    b'root:x:0:0:root:/root:/bin/bash
    '
    parent
    
    child1.stdout-->subprocess.PIPE
    child2.stdin<--subprocess.PIPE
    child2.stdout-->subprocess.PIPE
    
    利用communicate()实现交互:
    [root@oracle scripts]# cat stu_subprocess.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child1 = subprocess.Popen(['python'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    out,err = child1.communicate(b'print("hello")
    exit()')       继续给子进程输入信息
    # 启动一个子进程,然后控制其输入和输出
    print(out.decode('utf-8'))
    print('parent')
    [root@oracle scripts]# python stu_subprocess.py 
    hello
    
    parent
    [root@oracle scripts]# cat sub_popen2.py 
    #!/usr/bin/python
    #coding=utf8
    
    import subprocess
     
    obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    obj.stdin.write(b'print("hello")
    ')         stdin.write和communicate两者交换使用
    obj.stdin.write(b'print("world")')
     
    out,err = obj.communicate()
    print(out)
    [root@oracle scripts]# python sub_popen2.py 
    b'hello
    world
    '
    call():
    subprocess.call()
    父进程等待子进程完成
    返回退出信息(returncode,相当于Linux exit code)
    [root@oracle scripts]# cat sub_call.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.call(['ls','-l'],shell=False)
    print(type(child))
    print('parent')
    [root@oracle scripts]# python sub_call.py 
    total 12
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 135 Aug 21 15:45 sub_call.py
    -rw-r--r-- 1 root root 136 Aug 21 15:41 sub_popen.py
    <class 'int'>                call函数返回的是int
    parent
    调用call函数可以明显看出子进程阻塞了主进程的运行,先运行子进程,最后才是主进程
    [root@oracle scripts]# cat sub_call.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.call(['ls','-l'],shell=False)
    print(type(child))
    print(child)                  ----->returncode
    print('parent')
    [root@oracle scripts]# python sub_call.py        
    total 12
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py
    -rw-r--r-- 1 root root 149 Aug 21 15:47 sub_popen.py
    <class 'int'>
    0
    parent
    subprocess.call(*popenargs, **kwargs):运行命令。该函数将一直等待到子进程运行结束,并返回进程的returncode。如果子进程不需要进行交互,就可以使用该函数来创建。
    call函数返回的是returncode,也就是int类型
    
    根据shell类型不同,可以更改传入call函数的args类型:
    [root@oracle scripts]# cat sub_call.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.call("ls -l",shell=True)       
    print(type(child))
    print(child)
    print('parent')
    shell=True参数会让subprocess.call接受字符串类型的变量作为命令,并调用shell去执行这个字符串,当shell=False是,subprocess.call只接受数组变量作为命令,并将数组的第一个元素作为命令,剩下的全部作为该命令的参数。
    [root@oracle scripts]# python sub_call.py 
    total 40
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 143 Aug 21 17:22 sub_call.py
    -rw-r--r-- 1 root root 143 Aug 21 16:33 sub_check_output.py
    -rw-r--r-- 1 root root 162 Aug 21 17:17 sub_getoutput.py
    -rw-r--r-- 1 root root 279 Aug 21 16:17 sub_popen.py
    -rw-r--r-- 1 root root 148 Aug 21 16:29 sub_run.py
    -rw-r--r-- 1 root root 257 Aug 21 16:53 test_subprocess1.py
    -rw-r--r-- 1 root root 340 Aug 21 16:52 test_subprocess2.py
    -rw-r--r-- 1 root root 332 Aug 21 17:03 test_subprocess3.py
    -rw-r--r-- 1 root root 183 Aug 21 16:44 test_subprocess.py
    <class 'int'>
    0
    parent
    所以当shell默认为False时,args传入的值必须是列表,而不能是str
    from subprocess import call  
    import shlex  
    cmd = "cat test.txt; rm test.txt"  
    call(cmd, shell=True)
    shell介绍:
    https://zhidao.baidu.com/question/651286079254739125.html
    
    3.5新增的run():
    class subprocess.CompletedProcess
    The return value from run(), representing a process that has finished.
    [root@oracle scripts]# cat sub_run.py 
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.run(['ls','-l'],shell=False)
    print(type(child))
    print(child)
    print('parent')
    [root@oracle scripts]# python sub_run.py 
    total 16
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py
    -rw-r--r-- 1 root root 149 Aug 21 15:47 sub_popen.py
    -rw-r--r-- 1 root root 147 Aug 21 15:56 sub_run.py
    <class 'subprocess.CompletedProcess'>
    CompletedProcess(args=['ls', '-l'], returncode=0)
    parent
    
    check_output():
    [root@oracle scripts]# cat sub_check_output.py
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.check_output(['ls','-l'],shell=False)
    print(type(child))
    print(child)
    print('parent')
    [root@oracle scripts]# python sub_check_output.py
    <class 'bytes'>
    b'total 20
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py
    -rw-r--r-- 1 root root 156 Aug 21 16:26 sub_check_output.py
    -rw-r--r-- 1 root root 279 Aug 21 16:17 sub_popen.py
    -rw-r--r-- 1 root root 147 Aug 21 15:56 sub_run.py
    '
    parent
     
    [root@oracle scripts]# cat sub_check_output.py
    #!/usr/bin/python
    #coding=utf8
    import subprocess
    child = subprocess.check_output(['ls','-l'],shell=False)
    print(type(child))
    print('parent')
    [root@oracle scripts]# python sub_check_output.py
    <class 'bytes'>
    parent
    并没有打印出子进程运行后的内容
    
    subprocess.getoutput(cmd),返回的是一个字符串
    Return output (stdout and stderr) of executing cmd in a shell.
    [root@oracle scripts]# python sub_getoutput.py 
    <class 'str'>
    stu_subprocess.py
    sub_call.py
    sub_check_output.py
    sub_getoutput.py
    sub_popen.py
    sub_run.py
    test_subprocess1.py
    test_subprocess2.py
    test_subprocess3.py
    test_subprocess.py
    [root@oracle scripts]# cat sub_getoutput.py 
    #!/usr/bin/python
    #coding=utf8
    
    import subprocess
    
    def TestGetOutput():
      outp = subprocess.getoutput(["ls" ,"-l"])      列表
      print(type(outp))
      print(outp)
    
    TestGetOutput()
    [root@oracle scripts]# cat sub_getoutput.py 
    #!/usr/bin/python
    #coding=utf8
    
    import subprocess
    
    def TestGetOutput():
      outp = subprocess.getoutput("ls -l")        字符串
      print(type(outp))
      print(outp)
    
    TestGetOutput()
    [root@oracle scripts]# python sub_getoutput.py 
    <class 'str'>
    total 40
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py
    -rw-r--r-- 1 root root 143 Aug 21 16:33 sub_check_output.py
    -rw-r--r-- 1 root root 162 Aug 21 17:17 sub_getoutput.py
    -rw-r--r-- 1 root root 279 Aug 21 16:17 sub_popen.py
    -rw-r--r-- 1 root root 148 Aug 21 16:29 sub_run.py
    -rw-r--r-- 1 root root 257 Aug 21 16:53 test_subprocess1.py
    -rw-r--r-- 1 root root 340 Aug 21 16:52 test_subprocess2.py
    -rw-r--r-- 1 root root 332 Aug 21 17:03 test_subprocess3.py
    -rw-r--r-- 1 root root 183 Aug 21 16:44 test_subprocess.py
    
    #接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果 
    >>> subprocess.getstatusoutput('ls -l')     
    (0, 'total 40
    -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py
    -rw-r--r-- 1 root root 143 Aug 21 17:22 sub_call.py
    -rw-r--r-- 1 root root 143 Aug 21 16:33 sub_check_output.py
    -rw-r--r-- 1 root root 162 Aug 21 17:17 sub_getoutput.py
    -rw-r--r-- 1 root root 279 Aug 21 16:17 sub_popen.py
    -rw-r--r-- 1 root root 148 Aug 21 16:29 sub_run.py
    -rw-r--r-- 1 root root 257 Aug 21 16:53 test_subprocess1.py
    -rw-r--r-- 1 root root 340 Aug 21 16:52 test_subprocess2.py
    -rw-r--r-- 1 root root 332 Aug 21 17:03 test_subprocess3.py
    -rw-r--r-- 1 root root 183 Aug 21 16:44 test_subprocess.py')
    
     
  • 相关阅读:
    说说我当初是如何学Linux的
    案例八:shell自动化管理账本脚本
    案例七:shell实现开机自动播放挂载本地yum仓库程序
    案例六:shell脚本监控httpd服务80端口状态
    案例五:shell脚本实现定时监控http服务的运行状态
    案例四:Shell脚本生成随机密码
    案例三:shell统计ip访问情况并分析访问日志
    案例二:shell脚本获取当前日期和时间及磁盘使情况
    案例一:shell脚本指定日期减去一天
    Linux:保证数据安全落盘
  • 原文地址:https://www.cnblogs.com/jsonhc/p/7410224.html
Copyright © 2011-2022 走看看