无法理解Popen Function中的stdin和stdout在Python中是如何工作的

无法理解Popen Function中的stdin和stdout在Python中是如何工作的,python,Python,嗨,我是Python的初学者,喜欢通过Python的子流程模块执行shell命令。 但是对Popen构造函数有一些疑问 关于:参数stdin和stdout 假设我正在为ping一个网站编写脚本。通过shell命令将其设置为“www.google.com” 计划#1: stdout=subprocess.PIPE中到底发生了什么。如果我是对的,stdout用于标准输出。 那么为什么我们使用out=p.stdout.read(1) 如果我的程序是 import sys import subproce

嗨,我是Python的初学者,喜欢通过Python的子流程模块执行shell命令。 但是对Popen构造函数有一些疑问 关于:参数stdin和stdout

假设我正在为ping一个网站编写脚本。通过shell命令将其设置为“www.google.com”

计划#1:

  • stdout=subprocess.PIPE中到底发生了什么。如果我是对的,stdout用于标准输出。 那么为什么我们使用out=p.stdout.read(1)
  • 如果我的程序是

    import sys
    import subprocess
    cmdping = "ping -c4 10.10.22.20"
    p = subprocess.Popen(cmdping, shell=True,stdin=subprocess.PIPE,universal_newlines=True)
    
    输出如下所示:

    PING 10.10.22.20 (10.10.22.20) 56(84) bytes of data.
    
    64 bytes from 10.10.22.20: icmp_seq=1 ttl=63 time=0.951 ms
    
    UMR-AUTO root@1-2 #64 bytes from 10.10.22.20: icmp_seq=2 ttl=63 time=0.612 ms
    
    64 bytes from 10.10.22.20: icmp_seq=3 ttl=63 time=0.687 ms
    
    64 bytes from 10.10.22.20: icmp_seq=4 ttl=63 time=0.638 ms
    
    
    
    --- 10.10.22.20 ping statistics ---
    
    4 packets transmitted, 4 received, 0% packet loss, time 3002ms
    
    rtt min/avg/max/mdev = 0.612/0.722/0.951/0.134 ms
    
    你能给我解释一下吗

    我无法理解进程是如何发生的,我想准确地知道。

    A是一种将进程链接在一起的方法,以便它们可以使用标准流进行通信。下面是一个图表,解释了各种管道以及如何从wikipedia使用它们:

    这意味着您可以将一个流程的输出用作另一个流程的输入,并将这些流程链接在一起

    有三个主要区域可以插入管道。标准输出(stdout)、标准输入(stdin)和标准错误(stderr)流

    这允许您将输出重定向到其他应用程序。例如,您可能希望将所有错误输出重定向到将此输出发送到数据库的程序

    现在,当您想要在自己的程序中执行一个进程时,您必须决定如何与它通信。然而,在大多数情况下,有许多方便的方法可用。它们在下面使用管道,但提供了更友好的界面

  • 最简单的情况是当您只想运行一个进程时,您所关心的只是它是否成功运行。为此,您可以使用:

    还有
    子进程。请检查调用
    。它们都做相同的事情,唯一的区别是如果出现问题,
    check\u call
    将引发
    CallProcessError
    异常。您可以捕获此消息并输出错误消息

  • 要运行命令并获取输出,请执行以下操作:

    以下是它将返回的内容:

    >>> result = subprocess.check_output(['ping', '-c', '1', 'www.google.com'])
    >>> print(result)
    PING www.google.com (78.159.164.59) 56(84) bytes of data.
    64 bytes from 78.159.164.59: icmp_seq=1 ttl=49 time=33.4 ms
    
    --- www.google.com ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 33.414/33.414/33.414/0.000 ms
    
  • 运行一个进程,然后向它发送一些其他命令。为此,请使用和管道

    为了能够与流程通信,您需要创建一个管道,然后在程序中获取该管道的句柄

    如果您只想发送命令,您可以创建一个管道到
    stdin
    ,如果您想发送命令,然后读取结果-您需要创建一个pip到
    stdin
    ,和
    stdout
    (以及可选的stderr)

    在本例中,我们从python shell启动另一个python shell,然后执行
    import this
    ,并读取结果:

    >>> handle = subprocess.Popen(['python'],
                                  stdin=subprocess.PIPE,
                                  stderr=subprocess.PIPE,
                                  stdout=subprocess.PIPE, shell=True)
    >>> result, error = handle.communicate('import this')
    >>> print(result)
    The Zen of Python, by Tim Peters
    
    Beautiful is better than ugly.
    Explicit is better than implicit.
    Simple is better than complex.
    Complex is better than complicated.
    Flat is better than nested.
    Sparse is better than dense.
    Readability counts.
    Special cases aren't special enough to break the rules.
    Although practicality beats purity.
    Errors should never pass silently.
    Unless explicitly silenced.
    In the face of ambiguity, refuse the temptation to guess.
    There should be one-- and preferably only one --obvious way to do it.
    Although that way may not be obvious at first unless you're Dutch.
    Now is better than never.
    Although never is often better than *right* now.
    If the implementation is hard to explain, it's a bad idea.
    If the implementation is easy to explain, it may be a good idea.
    Namespaces are one honking great idea -- let's do more of those!
    
  • 最后,您会注意到我正在传递一个列表作为命令。这是列出要启动的命令(及其选项)的推荐方式

    您可以使用
    shlex
    模块帮助您将命令字符串分解为不同的组件:

    >>> import shlex
    >>> cmd = 'ping -c1 google.com'
    >>> parsed_cmd = shlex.split(cmd)
    >>> parsed_cmd
    ['ping', '-c1', 'google.com']
    

    这是一个简单的示例,但显示了一个更复杂的示例。

    您好,非常感谢您的回复。但是这个“handle.communicate('import this')”是什么意思呢。通常,Popen.communicate用于与进程通信并获取进程的输出。但是这个“import this”看起来很奇怪,我们也得到了这个
    的输出import this
    是我发送给进程的命令
    .communicate()
    是一个双向通道。没有任何参数
    handle.communicate()
    就可以得到结果。我从sys import*import subprocess handle=subprocess.Popen(['python'],stdin=subprocess.PIPE,stderr=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)结果,error=handle.communicate()打印(结果)但它显示的是空输出Yes,因为您没有发送任何要执行的内容。
    >>> result = subprocess.check_output(['ping', '-c', '1', 'www.google.com'])
    >>> print(result)
    PING www.google.com (78.159.164.59) 56(84) bytes of data.
    64 bytes from 78.159.164.59: icmp_seq=1 ttl=49 time=33.4 ms
    
    --- www.google.com ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 33.414/33.414/33.414/0.000 ms
    
    >>> handle = subprocess.Popen(['python'],
                                  stdin=subprocess.PIPE,
                                  stderr=subprocess.PIPE,
                                  stdout=subprocess.PIPE, shell=True)
    >>> result, error = handle.communicate('import this')
    >>> print(result)
    The Zen of Python, by Tim Peters
    
    Beautiful is better than ugly.
    Explicit is better than implicit.
    Simple is better than complex.
    Complex is better than complicated.
    Flat is better than nested.
    Sparse is better than dense.
    Readability counts.
    Special cases aren't special enough to break the rules.
    Although practicality beats purity.
    Errors should never pass silently.
    Unless explicitly silenced.
    In the face of ambiguity, refuse the temptation to guess.
    There should be one-- and preferably only one --obvious way to do it.
    Although that way may not be obvious at first unless you're Dutch.
    Now is better than never.
    Although never is often better than *right* now.
    If the implementation is hard to explain, it's a bad idea.
    If the implementation is easy to explain, it may be a good idea.
    Namespaces are one honking great idea -- let's do more of those!
    
    >>> import shlex
    >>> cmd = 'ping -c1 google.com'
    >>> parsed_cmd = shlex.split(cmd)
    >>> parsed_cmd
    ['ping', '-c1', 'google.com']