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