我想运行Linux字数统计实用程序wc来确定当前在/ var / log / syslog中的行数,因此我可以检测到它正在增长。我尝试了各种测试,当我从wc返回结果时,它既包括行数也包括命令(例如,var / log / syslog)。
所以它正在回归: 1338 / var / log / syslog 但我只想要行数,所以我想剥离/ var / log / syslog部分,并保留1338。
我尝试将其从bytestring转换为字符串,然后剥离结果,但没有快乐。转换为字符串和剥离,解码等的相同故事 - 都无法产生我正在寻找的输出。
这些是我得到的一些例子,在syslog中有1338行:
这是我编写的一些测试代码,试图破解这个问题,但没有解决方案:
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
答案 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 相同,但返回字符串输出而不是字节。这是直接替换。