zoukankan      html  css  js  c++  java
  • Python subprocess 模块

    注: 本文中代码均在shell中执行. 

    os.system 输出命令结果到屏幕, 返回命令执行状态. 

     若想将os.system的命令结果保存为一个变量, 要用到popen. 

    os.popen("dir").read() # 会保存命令的执行结果输出
    View Code

    要同时得到命令结果和命令执行状态, 需要用到subprocess.

    subprocess

    • 目的: 代替一些老的模块, 如os.system, os.spawn*. 
    • python 3.5之后才出现subprocess
    • 推荐的调用subprocess模块方法: 通过调用 run()方法来实现

    subprocess常用方法

    1. subprocess.Popen

    • 接收字符串格式命令, 返回元组形式, 第一个元素是执行状态, 第二个是命令结果.
    • subprocess.getstatusoutput('ls/bin/ls'),  返回 (0, '/bin/ls)
      • 该方法底层封装的是subprocess.Popen方法
      • 若要输出命令结果在屏幕上, 需要这样写 (以下是在shell里执行的脚本)
        • res = subprocess.Popen("ifconfig|grep 192", shell=True,stdout=subprocess.PIPE) 
        • res.stdout.read() 注: 若res里没有加stdout=subprocess.PIPE, 直接res.stdout是读不出来结果的(stdout代表标准输出). 相当于把命令结果存储在PIPE里(在内存里以管道的形式存储), 这样读取的时候就可以读出来. 每执行一个命令都会开辟一个新的管道, 所以不会堵.
      • 如果执行错误, 想要抓到错误信息, 需要再添加stderr (以下是在shell里执行的脚本):
        • res = subprocess.Popen("ifconfig|grep 192", shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        •  

          res.stderr.read()

    2. poll()

    • check if child process has terminated. returns returncode.
      • 每次调subprocess命令执行shell命令, 都相当于启了一个新的shell环境(相当于一个新的应用程序/一个新的进程)
      • 若一个进程太长, 不知道什么时候会执行完毕, 就需要定时去下, 就用到pulll.
        • res = subprocess.Popen("sleep 10; echo 'hello'", shell=True,stdout=subprocess.PIPE) 
        • res.stdout.read()  需要等到10秒之后才会返回结果
        • 因为不知道res什么时候执行完, 就定时去检查一下, 一旦执行完, 就去调结果:
          • res.poll()  返回NONE, 就是还没执行完; 返回0, 就是已经执行完了, 可以读结果了.

    3. wait()

    • wait for child process to terminate. returns returncode attribute.
    • 和pull()有点像, 也是检查是否执行完毕, 但是wait()会一直等, 直到执行完毕之后才会返回0代表已经出结果了; 不会像pull()一样, 若没执行完也会返回一个状态.

    4. terminate()

    • 杀掉所有启动进程 
    • 下面这段代码什么也读不出来, 因为进程中间被杀掉了:
      • res = subprocess.Popen("sleep 10; echo 'hello'", shell=True,stdout=subprocess.PIPE) 
      • res.terminate()
      • res.stdout.read()

    5. stdin()

    • 标准输入
    import subprocess
    
    obj = subprocess.Popen(["python"], stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    
    obj.stdin.write('print 1
    ') 
    obj.stdin.write('print 2
    ') 
    obj.stdin.write('print 3
    ') 
    obj.stdin.write('print 4
    ') 
    
    out_error_list = obj.communicate(timeout=10)
    print out_error_list
    • 例:
      • res = subprocess.Popen(['python3], shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE) 
      • res.stdin.write(b"print(1)") 必须在打印的内容前面加b, 代表byte类型, 否则会出错.
      • res.stdin.write(b"print(2)")
      • res.stdin.write(b"print(3)")
      • res.stdin.write(b"print(4)")
      • res.communicate()  把前面写的内容一次性读取出来

    subprocess常用参数

    1. args

    • shell 命令, 可以是字符串或者序列类型(如: list, 元组)

    2. bufsize

    • 指定缓冲. 0 -> 无缓冲, 1 -> 行缓冲, 其他 -> 缓冲区大小, 负值 -> 系统缓冲.

    3. preexec_fn

    • 只在Unix平台下有效, 用于指定一个可执行对象(callable object)

    4. close_fds

    • windows平台下, 如果close_fds被设置为True, 则新创建的子进程将不会继承父进程的输入,输出, 错误管道.

    5. shell

    • if shell is True, the specified command will be excuted through the shell. 

    6. pwd

    • 用于设置子进程的当前目录
    • 例:
      • res = subprocess.Popen(['pwd'], shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE, pwd="/tmp")
      • res.stdout.read() 返回b'/tmp ' 

    7. env

    • 用于指定子进程的环境变量. 如果env=NONE,子进程的环境变量将从父进程中继承.

    8. universal_newlines

    • 不同系统的换行符不同,True -> 同意使用 .

    9. startupinfo与createionflags

    • 只在windows下有效
    • 将被传递给底层的CreateProcess()函数, 用于设置子进程的一些属性, 如: 主窗口的外观,进程的优先级等.

    终端输入的命令分为两种:

    • 输入即可得到输出, 如: ifconfig
    • 输入进行某环境, 依赖再输入, 如: python

    sudo自动输密码

    import subprocess
    
    def mypass():
        mypass = '123' # 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,
                                           studout=subprocess.PIPE,
                                          )
    
    end_of_pipe = sudo.stdout
    print "Passowrd ok 
     Iptables Chains %s" % end_of_pipe.read()            

    以上是在linux里执行, 还可以通过python执行

     注: 上图通过python执行时, '123'要用单引号, 不能用双引号.  

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 数字黑洞
    Minifilter微过滤框架:框架介绍以及驱动层和应用层的通讯
  • 原文地址:https://www.cnblogs.com/cheese320/p/9120769.html
Copyright © 2011-2022 走看看