使用universal_newlines = True(使用bufsize = 1)和使用Popen的默认参数有什么区别?

时间:2016-07-04 09:41:27

标签: python python-3.x subprocess popen

我正在尝试读取从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会使输出"行缓冲"但我不确定这意味着什么。我很感激有关这些不同元素如何结合在一起的解释。感谢

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=Falsefor 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(您可以但不需要)。而且您不需要在案例中指定bufsizebufsize=1启用行缓冲模式(如果您要写入process.stdin,则会在换行符上自动刷新输入缓冲区),否则它等同于默认的bufsize=-1