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

Python 使用universal_newlines=True(bufsize=1)和使用Popen的默认参数有什么区别,python,python-3.x,subprocess,popen,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 Roboc

我试图读取从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

第一种方法不包括universal_newlines=True,因为文档中说明了这一点

第二个版本确实包含universal_新行,因此我指定了一个bufsize

有人能给我解释一下区别吗?我找不到这篇文章,但我确实读到了缓冲区溢出导致某种问题的问题,因此在stdout中使用
for line的重要性

此外,在查看输出时,不指定universal_换行符会使stdout成为
bytes
对象-但我不确定如果我只是使用
ascii
(新行和制表符)解码bytes对象与universal_换行符模式相比会有什么不同

最后,将
bufsize
设置为
1
会使输出“行缓冲”,但我不确定这意味着什么。如果能解释一下这些不同的元素是如何结合在一起的,我将不胜感激。谢谢

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

默认值是:
universal\u newlines=False
(意味着输入/输出被接受为字节,而不是Unicode字符串加上处理(因此参数的名称。Python 3.7提供了
文本
别名,在这里可能更直观)被禁用——您可以按原样获取二进制数据(除非Windows上的POSIX层搞砸了)和
bufsize=-1
(这意味着流被完全缓冲——使用默认缓冲区大小)

universal\u newlines=True
使用
locale.getpreferredencoding(False)
字符编码来解码字节(这可能不同于代码中使用的
ascii
编码)

如果
universal\u newlines=False
则对Robocopy中的行执行
。标准输出:
迭代
b'\n'
-分隔行。如果进程使用非ascii编码(例如UTF-16)进行输出,则即使系统上的
os.linesep='\n'
,也可能会得到错误的结果。如果要使用文本行,请使用文本模式:显式传递
universal\u newlines=True
或使用
io.TextIOWrapper(process.stdout)

第二个版本确实包含universal_新行,因此我指定了一个bufsize


通常,如果使用
universal\u newlines
(可以,但不是必需的),则无需指定
bufsize
bufsize=1
启用行缓冲模式(如果要写入
process.stdin
,输入缓冲区将在换行符上自动刷新)否则,它相当于默认值
bufsize=-1

,因此
bufsize=-1
的默认值似乎可能会导致问题。完全缓冲流可能会导致某种类型的阻塞,如果未指定(在通用\u换行模式下)同样,我不是因为缓冲区已满而创建了阻塞的可能性吗?@Startec:不是。这里没有阻塞问题(不管
universal\u newlines
bufsize
值如何)。您从哪里得到这些想法?如果您对某些特定代码有疑问,请询问有关此特定代码的问题。很抱歉,我的困惑来自子流程的文档(也就是说,
不要将stdout=PIPE或stderr=PIPE与此函数一起使用。如果子进程生成足够的输出到一个管道,以填充操作系统管道缓冲区,则子进程将被阻止,因为这些管道没有被读取。)
但我现在看到这是subprocess.call。感谢您的明确回答-它解决了我的问题@Startec:是的。如果您不读取
进程.stdout
管道(当
stdout=pipe
时),则子进程可能会阻塞,即操作系统管道缓冲区可能是有限的(至少在某些系统上),因此,一旦子进程填充它,它将无法再写入(直到通过从管道末端读取来耗尽缓冲区)。注意:OS管道缓冲区位于父Python脚本之外;它与
bufsize
(控制父Python脚本内的缓冲区)无关,
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