Python子进程check_输出比调用慢得多

Python子进程check_输出比调用慢得多,python,performance,subprocess,Python,Performance,Subprocess,我想知道为什么会这样。我正在调用一个命令来重新启动Ubuntu服务器12.04上的网络 快速执行 当我使用以下三种方式之一调用命令时,执行大约需要0.1秒: 直达终点站 使用os.system的python脚本 使用子流程调用的python脚本 终端会话: root@ubuntu:~# time /etc/init.d/networking restart * Running /etc/init.d/networking restart * Reconfiguring network int

我想知道为什么会这样。我正在调用一个命令来重新启动Ubuntu服务器12.04上的网络

快速执行

当我使用以下三种方式之一调用命令时,执行大约需要0.1秒:

  • 直达终点站
  • 使用
    os.system的python脚本
  • 使用
    子流程调用的python脚本
  • 终端会话:

    root@ubuntu:~# time /etc/init.d/networking restart
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m0.105s
    
    root@ubuntu:~# time python -c "import os;
    > os.system('/etc/init.d/networking restart')"
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m0.111s
    
    root@ubuntu:~# time python -c "import subprocess;
    > subprocess.call(['/etc/init.d/networking', 'restart'])"
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m0.111s
    
    root@ubuntu:~# time python -c "import subprocess;
    > print subprocess.check_output(['/etc/init.d/networking', 'restart'])"
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m23.201s
    
    root@ubuntu:~# time python -c "from subprocess import Popen, PIPE;
    > print Popen(['/etc/init.d/networking', 'restart'], stdout=PIPE).stdout.read()"
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m23.201s
    
    执行缓慢

    但是,如果我使用
    子流程,请检查\u output
    或Popen并尝试读取输出,这需要23秒。慢多了。似乎只有当我尝试使用一个返回命令输出的函数时,这种巨大的差异才会发生。我想了解为什么会发生这种情况,并找到一个解决方案来执行这个命令并获得它的输出,而不需要花费太长时间

    终端会话:

    root@ubuntu:~# time /etc/init.d/networking restart
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m0.105s
    
    root@ubuntu:~# time python -c "import os;
    > os.system('/etc/init.d/networking restart')"
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m0.111s
    
    root@ubuntu:~# time python -c "import subprocess;
    > subprocess.call(['/etc/init.d/networking', 'restart'])"
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m0.111s
    
    root@ubuntu:~# time python -c "import subprocess;
    > print subprocess.check_output(['/etc/init.d/networking', 'restart'])"
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m23.201s
    
    root@ubuntu:~# time python -c "from subprocess import Popen, PIPE;
    > print Popen(['/etc/init.d/networking', 'restart'], stdout=PIPE).stdout.read()"
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m23.201s
    
    更新

    其中一条评论建议尝试使用tee命令。结果很有趣。在没有python参与的终端中,如果使用tee,则需要同样的23秒。我仍然很好奇为什么,但至少这可能会提供更多关于发生了什么的线索

    root@ubuntu:~# time /etc/init.d/networking restart | tee out.txt
     * Running /etc/init.d/networking restart
     * Reconfiguring network interfaces...
    real    0m23.181s
    

    下面的代码基于J.F.Sebastian的精彩评论。下面的代码按预期在0.1秒内运行,并将命令的输出返回到字符串

    from subprocess import check_call, STDOUT
    from tempfile import NamedTemporaryFile
    
    with NamedTemporaryFile() as f:
        check_call(['/etc/init.d/networking', 'restart'], stdout=f, stderr=STDOUT)
        f.seek(0)
        output = f.read()
    

    我不知道以下两项是否相关(,),但有一个答案建议将
    close_fds=True
    添加到popen参数
    subprocess.call()
    只是
    subprocess.popen(*popenargs,**kwargs)。wait()
    @jwpat7谢谢链接。我尝试了close_fds=True,但没有任何区别。执行所需的时间:
    网络重启|打开某个_文件
    (检查某个_文件是否为空)。尝试
    bufsize=-1
    和/或
    f=TemporaryFile();检查调用(cmd,stdout=f,stderr=stdout);f、 寻求(0);output=f.read()
    @J.f.Sebastian这些建议太棒了。我在问题中发布了tee的结果,输出的文件不是空的,它包含输出。你的临时文件方法非常有效。如果你把它贴在下面,我可以投你一票。我还是不明白为什么会发生这种事。