管道命令与看似几个单独的输出到文件

时间:2017-10-13 20:53:44

标签: python subprocess

我正在使用speedtest-cli在python脚本中获取我的网速。我想通过subprocess.Popen在shell中运行此命令。

这是终端中的命令:

`speedtest-cli --share > output.log`

speedtest-cli运行测试,而--share在输出中为我提供了一个额外的链接,指向最快结果的图像。以下是output.log

的内容
  

检索speedtest.net配置...   从M-net测试(xxx.xxx.xxx.xxx)......   检索speedtest.net服务器列表...   根据ping选择最佳服务器...   主持者XXXXXXXXXXXXXXXXXXXXXX [16.12 km]:20.902 ms   测试下载速度............................................... .................................   下载:48.32 Mbit / s   测试上传速度............................................... .................................................. .....   上传:12.49 Mbit / s   分享结果:http://www.speedtest.net/result/670483456.png

如果我在终端中运行命令,我会按预期获得所有测试结果以及目标文件中的链接。我使用此grep trick确认全部为stdout而非其他渠道:command | grep .

我试图在Python中运行它,如下所示:

subprocess.Popen(['speedtest-cli', '--share', '>', 'output.log`],
                  stdout=subprocess.PIPE, shell=True)

...我也尝试通过python直接将输出放入文件中:

with open('output.log', 'w') as f:
    Popen(['speedtest-cli', '--json', '--share'], stdout=f, shell=True)

这些都不奏效。我用后一种方法创建了一个很好的文件,但链接不包括在内! (上面输出的最后一行)。

使用subprocess模块反对所有弃用警告和更好的安全性,我变得绝望并尝试os.system()

os.system('speedtest-cli --share > output.log')

令人讨厌的是,这有效......在文件中捕获了完整的输出以及链接。

这里发生了什么?如何使用Popen

获取要捕获的链接

我使用的是Python 3.5

1 个答案:

答案 0 :(得分:2)

使用shell=True时,Popen的参数需要是字符串,而不是列表:

subprocess.Popen('speedtest-cli --json --share > output.log',
                 stdout=subprocess.PIPE, shell=True)

比较

>>> subprocess.Popen('echo hello', shell=True)
>>> hello

>>> subprocess.Popen(['echo', 'hello'], shell=True)
>>> 

当您传递列表并且使用shell=True时,只有第一项是相关的,其余部分将被忽略。

如果您想自己收集输出,请考虑subprocess.check_output

>>> output = subprocess.check_output(['echo', 'hello'])
>>> output
b'hello\n'

或者:

>>> output = subprocess.check_output('echo hello', shell=True)

check_output方法适用于Python 2和Python 3.在Python 3中,您还可以使用run方法。