Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python3子进程输出_Python_Python 3.x_Subprocess - Fatal编程技术网

Python3子进程输出

Python3子进程输出,python,python-3.x,subprocess,Python,Python 3.x,Subprocess,我想运行Linux单词计数实用程序wc来确定/var/log/syslog中当前的行数,这样我就可以检测到它正在增长。我尝试了各种测试,当我从wc返回结果时,它包括行计数和命令(例如var/log/syslog) 所以它又回来了: 1338/var/log/syslog 但是我只需要行计数,所以我想去掉/var/log/syslog部分,只保留1338 我曾尝试将其从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标准数据:1338/var/log/syslog


我建议您使用
subprocess.getoutput()
,因为它完全按照您的要求在shell中运行命令并获取其结果(与输出相反)。然后,您可以从返回的字符串列表中获取第一个元素

试试这个:

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

为了避免在*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)

由于Python3.6,您可以通过给它一个编码参数,使
check_output()
返回一个
str
,而不是
bytes

check_output('wc --lines /var/log/syslog', encoding='UTF-8')
但是,由于您只需要计数,而且
split()
int()
都可以与
字节一起使用,因此无需为编码而烦恼:

linecount = int(check_output('wc -l /var/log/syslog').split()[0])
虽然使用外部程序可能会更容易一些(例如,计算由
journalctl
打印的日志行条目),但在这种特殊情况下,您不需要使用外部程序。最简单的纯Python解决方案是:

with open('/var/log/syslog', 'rt') as f:
    linecount = len(f.readlines())

这样做的缺点是它会将整个文件读入内存;如果是一个大文件,请在打开文件之前初始化
linecount=0
,并对f:linecount+=1中的行使用
循环,而不是
readlines()
,以便在计算时在内存中只保留文件的一小部分。

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

从文档:

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

类似于此,但使用subprocess.run()会更复杂一些:


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

应该警告您,
subprocess.getoutput
属于遗留Shell调用函数的类别()。@belacqua:17.5.6下面的段落。旧式Shell调用函数说()--cite(重点添加):这些操作隐式调用系统Shell,上述关于安全性和异常处理一致性的保证对这些函数都无效。@belacqua:the
subprocess.check_function()
()是更好的替代品,也需要更少的工作。看J.F.塞巴斯蒂安的。参数也可以是字符串。@pepr我相信你的意思是说
检查输出
,而不是检查函数..?是的,@GregSadetsky。我的错在这种情况下,有没有办法获取
sys.stdout.encoding
,因此我们将其传递给解码,而不是
ascii
?如果我们
subprocess.PIPE
stdout怎么办?@Mr_and_Mrs_D这将是一件错误的事情:1-在一般情况下,它不会有帮助(文件名可能是一个字节序列,任何字符编码都无法对其进行编码,正如答案中明确指出的那样。请参阅PEP 383)2-ascii在这里起作用(在Python支持的任何语言环境中解码wc打印的数字)另外,在Python 3.7上有一个capture_output=True谢谢。我不知道结果开头的b'…是什么。一次只在内存中读取一行来计算行数的好方法是
sum(f中的行为1)
如果可以的话,还可以查看避免使用shell=True的许多原因,例如在您的案例中。
subprocess.check_output('wc -l /path/to/your/file | cut -d " " -f1', universal_newlines=True, shell=True)
subprocess.run(command, shell=True, check=True, universal_newlines=True, stdout=subprocess.PIPE).stdout