zoukankan      html  css  js  c++  java
  • python笔记65

    前言

    subprocess 模块允许我们启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值。
    Popen 是 subprocess的核心,子进程的创建和管理都靠它处理。

    subprocess.Popen

    subprocess模块定义了一个类: Popen

    class Popen(object):
        """ Execute a child program in a new process.
    
        For a complete description of the arguments see the Python documentation.
    
        Arguments:
          args: A string, or a sequence of program arguments.
    
          bufsize: supplied as the buffering argument to the open() function when
              creating the stdin/stdout/stderr pipe file objects
    
          executable: A replacement program to execute.
    
          stdin, stdout and stderr: These specify the executed programs' standard
              input, standard output and standard error file handles, respectively.
    
          preexec_fn: (POSIX only) An object to be called in the child process
              just before the child is executed.
    
          close_fds: Controls closing or inheriting of file descriptors.
    
          shell: If true, the command will be executed through the shell.
    
          cwd: Sets the current directory before the child is executed.
    
          env: Defines the environment variables for the new process.
    
          universal_newlines: If true, use universal line endings for file
              objects stdin, stdout and stderr.
    
          startupinfo and creationflags (Windows only)
    
          restore_signals (POSIX only)
    
          start_new_session (POSIX only)
    
          pass_fds (POSIX only)
    
          encoding and errors: Text mode encoding and error handling to use for
              file objects stdin, stdout and stderr.
    
        Attributes:
            stdin, stdout, stderr, pid, returncode
        """
        _child_created = False  # Set here since __del__ checks it
    
        def __init__(self, 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):
            """Create new Popen instance."""
    

    常用参数:

    • args:shell命令,可以是字符串或者序列类型(如:str, list,元组)
    • bufsize:缓冲区大小。当创建标准流的管道对象时使用,默认-1。
      0:不使用缓冲区
      1:表示行缓冲,仅当universal_newlines=True时可用,也就是文本模式
      正数:表示缓冲区大小
      负数:表示使用系统默认的缓冲区大小。
    • stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
    • preexec_fn:只在 Unix 平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
    • shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。
    • cwd:用于设置子进程的当前目录。
    • env:用于指定子进程的环境变量。如果 env = None,子进程的环境变量将从父进程中继承。
    • encoding:设置编码类型

    使用示例

    一个简单示例,命令行执行pip

    import subprocess
    p = subprocess.Popen('pip -V',
                         shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT,
                         )
    
    # 输出stdout
    print(p.communicate()[0])
    

    得到结果是byte类型的

    b'pip 21.1.2 from e:\python36\lib\site-packages\pip (python 3.6)
    
    '
    

    于是可以添加encoding参数utf-8

    import subprocess
    p = subprocess.Popen('pip -V',
                         shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT,
                         encoding='utf-8'
                         )
    
    # 输出stdout
    print(p.communicate()[0])
    
    

    此时输出

    pip 21.1.2 from e:python36libsite-packagespip (python 3.6)
    

    如果输出有中文,会出现解码异常
    输入java,正常情况是可以输出中文的

    import subprocess
    p = subprocess.Popen('java',
                         shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT,
                         encoding='utf-8'
                         )
    
    # 输出stdout
    print(p.communicate()[0])
    

    但是运行结果就会解码异常

    Traceback (most recent call last):
      File "D:/tests.py", line 44, in <module>
        print(p.communicate()[0])
      File "E:python36libsubprocess.py", line 830, in communicate
        stdout = self.stdout.read()
      File "E:python36libcodecs.py", line 321, in decode
        (result, consumed) = self._buffer_decode(data, self.errors, final)
    UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd3 in position 0: invalid continuation byte
    

    原因是windows系统编码是gb2312

    windows解码

    知道windows系统的编码后,设置对应的编码,就可以正常解码了

    import subprocess
    p = subprocess.Popen('java',
                         shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT,
                         encoding='gb2312'
                         )
    
    # 输出stdout
    print(p.communicate()[0])
    
    

    得到

    用法: java [-options] class [args...]
               (执行类)
       或  java [-options] -jar jarfile [args...]
               (执行 jar 文件)
    其中选项包括:
        -d32	  使用 32 位数据模型 (如果可用)
        -d64	  使用 64 位数据模型 (如果可用)
        -server	  选择 "server" VM
                      默认 VM 是 server.
    

    也可以在拿到输出结果后decode解码

    import subprocess
    p = subprocess.Popen('java',
                         shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT,
                         )
    # 输出stdout
    result = p.communicate()[0]
    print(result.decode('gb2312'))
    

    执行python代码,得到stdout内容

    接下来写一小段python代码,看执行结果

    # xx.py
    print("hello world! 这段包含了中文")
    

    使用subprocess.Popen执行,需设置encoding='utf-8'

    import subprocess
    p = subprocess.Popen(['python', 'xx.py'],
                         shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT,
                         encoding='utf-8'
                         )
    
    # 输出stdout
    print(p.communicate()[0])
    

    运行结果

    hello world! 这段包含了中文
    

    如果python代码有语法异常

    # xx.py
    print("hello world! 这段包含了中文"x)
    

    此时是可以输出异常内容的

      File "xx.py", line 1
        print("hello world! 这段包含了中文"x)
                                    ^
    SyntaxError: invalid syntax
    

    Popen 对象方法

    Popen 对象方法用到的几个方法

    • poll(): 检查进程是否终止,如果终止返回 returncode,否则返回 None。
    • wait(timeout): 等待子进程终止。
    • communicate(input,timeout): 和子进程交互,发送和读取数据。
    • send_signal(singnal): 发送信号到子进程 。
    • terminate(): 停止子进程,也就是发送SIGTERM信号到子进程。
    • kill(): 杀死子进程。发送 SIGKILL 信号到子进程。

    其它方法参考菜鸟教程https://www.runoob.com/w3cnote/python3-subprocess.html

  • 相关阅读:
    June 26th 2017 Week 26th Monday
    June 25th 2017 Week 26th Sunday
    June 24th 2017 Week 25th Saturday
    June 23rd 2017 Week 25th Friday
    June 22nd 2017 Week 25th Thursday
    2018最佳网页设计:就是要你灵感爆棚!!!
    图片素材类Web原型制作分享-Pexels
    想要打动HR的心,UX设计师求职信究竟应该怎么写?
    【UXPA大赛企业专访】Mockplus:“设计替代开发”将成为现实
    2018年最好的医疗网站设计及配色赏析
  • 原文地址:https://www.cnblogs.com/yoyoketang/p/15353481.html
Copyright © 2011-2022 走看看