Python3子进程输出

时间:2013-08-14 23:43:40

标签: python python-3.x subprocess bytestring

我想运行Linux字数统计实用程序wc来确定当前在/ var / log / syslog中的行数,因此我可以检测到它正在增长。我尝试了各种测试,当我从wc返回结果时,它既包括行数也包括命令(例如,var / log / syslog)。

所以它正在回归:    1338 / var / log / syslog 但我只想要行数,所以我想剥离/ var / log / syslog部分,并保留1338。

我尝试将其从bytestring转换为字符串,然后剥离结果,但没有快乐。转换为字符串和剥离,解码等的相同故事 - 都无法产生我正在寻找的输出。

这些是我得到的一些例子,在syslog中有1338行:

  • b'1338 / var / log / syslog \ n'
  • 1338 / var / log / syslog

这是我编写的一些测试代码,试图破解这个问题,但没有解决方案:

import subprocess

#check_output returns byte string
stdoutdata = subprocess.check_output("wc --lines /var/log/syslog", shell=True)
print("2A stdoutdata: " + str(stdoutdata))
stdoutdata = stdoutdata.decode("utf-8")
print("2B stdoutdata: " + str(stdoutdata))    
stdoutdata=stdoutdata.strip()
print("2C stdoutdata: " + str(stdoutdata))    

这个输出是:

  • 2A stdoutdata:b'1338 / var / log / syslog \ n'

  • 2B stdoutdata:1338 / var / log / syslog

  • 2C stdoutdata:1338 / var / log / syslog

  • 2D stdoutdata:1338 / var / log / syslog

5 个答案:

答案 0 :(得分:57)

我建议您使用subprocess.getoutput(),因为它完全符合您的要求 - 在shell中运行命令并获取其string output(而不是byte string输出)。然后你可以split on whitespace并从返回的字符串列表中获取第一个元素。

试试这个:

import subprocess
stdoutdata = subprocess.getoutput("wc --lines /var/log/syslog")
print("stdoutdata: " + stdoutdata.split()[0])

答案 1 :(得分:10)

为避免在* nix上调用shell并解码可能是任意字节序列('\0'除外)的文件名,您可以将该文件作为stdin传递:

import subprocess

with open(b'/var/log/syslog', 'rb') as file:
    nlines = int(subprocess.check_output(['wc', '-l'], stdin=file))
print(nlines)

或者您可以忽略任何解码错误:

import subprocess

stdoutdata = subprocess.check_output(['wc', '-l', '/var/log/syslog'])
nlines = int(stdoutdata.decode('ascii', 'ignore').partition(' ')[0])
print(nlines)

答案 2 :(得分:2)

自Python 3.6起,您可以通过为其赋予 encoding 参数,使check_output()返回str而不是bytes

check_output('wc --lines /var/log/syslog', encoding='UTF-8', shell=True)

答案 3 :(得分:1)

相当于Curt J. Sampson的答案也就是这个(它返回一个字符串):

subprocess.check_output('wc -l /path/to/your/file | cut -d " " -f1', universal_newlines=True, shell=True)

来自文档:

  

如果指定了编码或错误,或者文本为true,则文件对象为   使用指定的文本模式打开stdin,stdout和stderr   编码和错误或io.TextIOWrapper默认值。的   Universal_newlines参数等效于文本,并提供给   向后兼容。默认情况下,文件对象以二进制形式打开   模式。

有点类似,但是使用subprocess.run()有点复杂:

subprocess.run(command, shell=True, check=True, universal_newlines=True, stdout=subprocess.PIPE).stdout

作为subprocess.check_output()可能等同于subprocess.run()。

答案 4 :(得分:0)

getoutput(以及更接近的替代品 getstatusoutput)不是 check_output 的直接替代品 - 3.x 中的安全更改阻止了某些以前的命令以这种方式工作(我的脚本试图使用 iptables 并使用新命令失败)。更好地适应新的python3输出并添加参数universal_newlines=True:

check_output(command, universal_newlines=True)

此命令的行为与您期望的 check_output 相同,但返回字符串输出而不是字节。这是直接替换。