为什么`print foo.communicate()[0]`与`print foo.communicate()`不同?

1 投票
2 回答
710 浏览
提问于 2025-04-15 21:21

这是一个情况:

我正在运行一个命令:

import subprocess
foo = subprocess.Popen('ls /', shell=True, stdout=subprocess.PIPE,\
stderr=subprocess.STDOUT)

这很简单,对吧?我发现我可以用 .communicate() 来处理输出,像这样:

print foo.communicate()

这样做效果很好,产生的输出和文档中说的结果一样,是一个元组:

('bin\nboot\ncdrom\n[...stuff redacted for brevity...]tmp\nusr\nvar\nvmlinuz\n', None)

注意里面有 \n 换行符。我发现只要请求元组的第一个元素,就会得到带有换行符的输出,像这样:

>>> print foo.communicate()[0]
bin
boot
cdrom
[...stuff redacted for brevity...]
tmp
usr
var
vmlinuz

但我不明白的是,为什么只打印第一个元素就会产生换行符。别误会,这样很好,我很高兴可以不使用循环就做到这一点,但我想理解这背后发生了什么。

2 个回答

2

foo.communicate() 会返回一个元组(tuple)。如果你写 foo.communicate()[0],那么你就能拿到这个元组里的第一个元素。因为这个元素只是一个字符串,所以 Python 解释器会把它打印到你的屏幕上,并把 \n 显示成换行。

当你打印 foo.communicate() 返回的元组时,你会看到 \n 字符,但这只是元组打印方式的不同,换行符实际上是一直存在的。

3

在Python中,当你调用类似于 print obj 的代码时,其实是在调用这个对象的 __str__ 方法,然后把结果当作字符串来处理。

举个例子,假设你有:

      >>> a = ('foo\nbar', '5')
      >>> print a
      ('foo\nbar', '5')

你可能已经注意到了。但是如果你做一些像这样的事情:

      >>> class mytuple(tuple):
              def __str__(self):
                  return ''.join(self)
      >>> b = mytuple(a)
      >>> print b
      foo
      bar5

这个元组类型的子类超越了标准的 __str__ 方法,构建了一个字符串,这个字符串是由它内部各个部分的字符串表示组合而成的。

之所以一般情况下不这样做,是因为你永远不知道一个元组或列表里可能放入什么对象,并不是所有对象都有可以转换成字符串的表示方式。

撰写回答