Python 显示subprocess.Popen的输出,就像在终端中运行一样

Python 显示subprocess.Popen的输出,就像在终端中运行一样,python,subprocess,ipython,Python,Subprocess,Ipython,我使用的是ipython,当我运行上面的命令时,控制台上不会打印任何内容。有没有办法在控制台窗口中看到与在linux终端上直接运行命令相同的输出?您正在将dstat命令的CSV输出写入stats.CSV文件 输出应该从stats.csv文件读取,而不是从stdout读取,除非您删除命令中传递的--output选项。在写下下面的答案后,我记得有一种方法可以突破IPython,像shell一样运行。特别是,如果您的行以感叹号(!)开头,IPython将像在命令行上一样执行命令 例如,如果我运行!ds

我使用的是
ipython
,当我运行上面的命令时,控制台上不会打印任何内容。有没有办法在控制台窗口中看到与在linux终端上直接运行命令相同的输出?

您正在将
dstat
命令的CSV输出写入
stats.CSV
文件


输出应该从
stats.csv
文件读取,而不是从stdout读取,除非您删除命令中传递的
--output
选项。

在写下下面的答案后,我记得有一种方法可以突破IPython,像shell一样运行。特别是,如果您的行以感叹号(
)开头,IPython将像在命令行上一样执行命令

例如,如果我运行
!dstat--output stats.csv
,我得到以下结果:

我仍然沿用下面的基于自定义代码的方法,因为编写它很有趣,但显然,内置解决方案(即,在命令前面加上
)可能更适合您的使用


此点以下的自定义解决方案 这个怎么样

  subprocess.Popen('dstat --output stats.csv', shell=True, stdout=subprocess.PIPE).stdout.read()
在Ubuntu上运行Python 3.7.3的IPython的输出:


代码并不特别漂亮,但您可以轻松地将其放入自己的模块中,然后调用函数。我对IPython内部的结果相当满意。(输出感觉相当自然。)

子流程。检查调用('dmesg | tail-3',shell=True,universal\u newlines=True)
对我来说很好。你在命令发布前对标准输出做了什么吗?谢谢Spencer D,两种方法都很有效!遗憾的是,
local_命令('echo“Hello,World”)
在Spyder或Jupyter中使用ipython时返回一个
不支持操作:fileno
异常。你知道这个错误的原因吗?@HappyPy,这很奇怪。这是否发生在
'stdin':sys.stdin.fileno(),
行上?无论哪种方式,我都会在我这方面做一点调查,因为我没想到这会成为一个问题。也许Jupyter和Spyder会更改默认的STDIO句柄,以便在接口中显示所有I/O。我想如果他们用泛型流替换这些流,那么这些流可能没有
fileno()
方法。根据,如果方法未实现,则应抛出
UnsupportedOperation
。@HappyPy,好的,正如我之前的评论中所怀疑的,Spyder似乎用
ipykernel.iostream.OutStream
类的实例替换了
sys.stdout
。该类的pydocs将其描述为:
一个类似文件的对象,它将流发布到0MQ发布套接字。输出被传递给一个IO线程。
基于
inspect.getsource(ipykernel.iostream.OutStream)
,该模块似乎没有实现
fileno()
,因此
fileno()
方法由
TextIOBase
父类解决,该父类引发了。我将稍微处理一下,看看是否可以使用
local\u命令(…)
"""Simulate command-line execution."""
import os
import sys
import subprocess
import signal
from time import sleep


def local_command(command):
    """Simulate command execution as if on command-line."""
    env_to_pass = dict(os.environ)
    kwargs_for_popen = {
        'shell': True,
        'bufsize': 1,
        'stdin': sys.stdin.fileno(),
        'stdout': sys.stdout.fileno(),
        'stderr': sys.stderr.fileno(),
        'env': env_to_pass
    }
    # Determine which keyword we should use for putting the process I/O into
    # text-only mode.
    if sys.hexversion >= 0x3070000:
        # "text" was added as a keyword argument alias for "universal_newlines"
        # in Python 3.7, and "universal_newlines" is provided still only for
        # backwards compatibility. Let's do this right if we're going to do it.
        kwargs_for_popen['text'] = True
    else:
        # For systems with python before 3.7, use "universal_newlines"
        kwargs_for_popen['universal_newlines'] = True

    sp = subprocess.Popen(command, **kwargs_for_popen)
    while True:
        try:
            while sp.poll() is None:
                sleep(0.02)
        except KeyboardInterrupt:
            sp.send_signal(signal.SIGINT)
            sleep(0.02)
        if sp.poll() is not None:
            # Process has terminated.
            # Exit event loop.
            break
    # end while

    sp_stdout_data, sp_stderr_data = sp.communicate()
    print(sp_stdout_data)
    return sp.returncode