我正在尝试读取从Python调用的子进程的输出。要做到这一点,我使用的是Popen(因为如果使用subprocess.call,我认为不可能管道stdout。)
截至目前,我有两种方法可以做到这一点,在测试中,它似乎提供了相同的结果。代码如下:
with Popen(['Robocopy', source, destination, '/E', '/TEE', '/R:3', '/W:5', '/log+:log.txt'], stdout=PIPE) as Robocopy:
for line in Robocopy.stdout:
line = line.decode('ascii')
message_list = [item.strip(' \t\n').replace('\r', '') for item in line.split('\t') if item != '']
print(message_list[0], message_list[0])
Robocopy.wait()
returncode = Robocopy.returncode
和
with Popen(['Robocopy', source, destination, '/E', '/TEE', '/R:3', '/W:5', '/log+:log.txt'], stdout=PIPE, universal_newlines=True, bufsize=1) as Robocopy:
for line in Robocopy.stdout:
message_list = [item.strip() for item in line.split('\t') if item != '']
print(message_list[0], message_list[2])
Robocopy.wait()
returncode = Robocopy.returncode
第一种方法不包括universal_newlines = True,因为文档说明这是only usable if universal_newlines=True i.e., in a text mode。
第二个版本包含universal_newlines,因此我指定了bufsize。
有人可以向我解释一下这个区别吗?我找不到这篇文章,但我确实读过有关溢出缓冲区的问题导致某种问题,因此使用for line in stdout
的重要性。
此外,在查看输出时,未指定universal_newlines使stdout成为bytes
对象 - 但我不确定如果我用ascii
解码字节对象会产生什么差异(就新行和制表符)比较universal_newlines模式。
最后,将bufsize
设置为1
会使输出"行缓冲"但我不确定这意味着什么。我很感激有关这些不同元素如何结合在一起的解释。感谢
答案 0 :(得分:8)
使用universal_newlines = True(使用bufsize = 1)和使用Popen的默认参数
之间的区别
默认值为: universal_newlines=False
(意味着输入/输出被接受为字节,而不是Unicode字符串加上{ {3}}处理(因此参数的名称.Python 3.7提供了text
别名,这里可能更直观)被禁用 - 你按原样获得二进制数据(除非Windows上的POSIX层混乱)和 bufsize=-1
(意味着流已完全缓冲 - 使用默认缓冲区大小)。
universal_newlines=True
使用locale.getpreferredencoding(False)
字符编码来解码字节(可能与代码中使用的ascii
编码不同)。
如果universal_newlines=False
则for line in Robocopy.stdout:
重复b'\n'
- 分隔的行。如果进程使用非ascii编码,例如,UTF-16用于输出,那么即使系统上有os.linesep == '\n'
;你可能得到错误的结果。如果您要使用文本行,请使用文本模式:传递universal_newlines=True
或明确使用io.TextIOWrapper(process.stdout)
。
第二个版本包含universal_newlines,因此我指定了bufsize。
一般情况下,如果您使用bufsize
,则无需指定universal_newlines
(您可以但不需要)。而且您不需要在案例中指定bufsize
。 bufsize=1
启用行缓冲模式(如果您要写入process.stdin
,则会在换行符上自动刷新输入缓冲区),否则它等同于默认的bufsize=-1
。