python - 使用子进程的 PIPE 时如何以字符串形式获取 python 对象 <class '_io.TextIOWrapper' > 的内容?

标签 python python-3.x encoding subprocess

我有一个问题。我的子进程模块正在吐出一些我不知道如何处理的东西。

在 Arch Linux 上使用 Python 3。

命令包括:​​

  • svn 信息
  • grep -IEi
  • sed -e

尽管我的终端输出为 3 作为修订号,但我似乎无法将此值存储到 Python 变量中。它与我获取一个对象有关,而不是与我怀疑的该对象的内容有关。任何帮助将不胜感激。

为了完整起见,我演示了参数 universal_lines 如何影响输出。

假设我的系统上的 svn 版本是 3:

使用shell=True,cwd=branch,universal_lines=False

#!/usr/bin/env python
import os
import subprocess

branch = '/home/username/svncheckoutfolder'
command = 'svn info "%s" | grep -IEi "Revision:" | sed -e "s/^Revision: \\([0-9]*\\)/\\1/g"' % (branch) # filters out revision number from svn info command
process = subprocess.Popen(command,stdout=subprocess.PIPE,shell=True,cwd=branch) # cwd=branch is only necessary when command contains LaTeX interpreter. In this case, I included the absolute path within the command.
process_stdout = process.communicate()[0]
current_revision = process.stdout # This should be a revision number.
print (type(current_revision)) # <class '_io.BufferedReader'>
print (current_revision) # <_io.BufferedReader name=3>

结果:

<class '_io.BufferedReader'>
<_io.BufferedReader name=3>

使用shell=True、cwd=branch、universal_lines=True

#!/usr/bin/env python
import os
import subprocess

branch = '/home/username/svncheckoutfolder'
command = 'svn info "%s" | grep -IEi "Revision:" | sed -e "s/^Revision: \\([0-9]*\\)/\\1/g"' % (branch) # filters out revision number from svn info command
process = subprocess.Popen(command,stdout=subprocess.PIPE,shell=True,cwd=branch) # cwd=branch is only necessary when command contains LaTeX interpreter. In this case, I included the absolute path within the command.
process_stdout = process.communicate()[0]
current_revision = process.stdout # This should be a revision number.
print (type(current_revision)) # <class '_io.TextIOWrapper'>
print (current_revision) # <_io.TextIOWrapper name=3 encoding='UTF-8'>

结果:

<class '_io.TextIOWrapper'>
<_io.TextIOWrapper name=3 encoding='UTF-8'>

我尝试读取该对象,但这也不起作用:

print(current_revision.read())

结果:

ValueError: read of closed file

最佳答案

您没有在此处使用 Popen.communicate() 的返回值:

current_revision = process.stdout

您正在引用用于与 shell 通信的 subprocess 模块的(现已关闭)文件对象。您完全忽略了上一行返回的值。

只需使用:

process_stdout = process.communicate()[0]
current_revision = process_stdout.decode('utf8').strip()

不使用universal_newlines=True时,或

process_stdout = process.communicate()[0]
current_revision = process_stdout.strip()

当你这样做的时候。数据包含换行符,因此调用 str.strip()

您可以使用 subprocess.check_output() function ,如果您需要的只是命令的标准输出:

output = subprocess.check_output(
    command, shell=True, cwd=branch, universal_newlines=True)

最后但并非最不重要的一点是,让 Python 来解析响应可能会更简单:

command = ('svn', 'info', branch)
output = subprocess.check_output(command, universal_newlines=True)
revision = None
for line in output.splitlines():
    if line.startswith('Revision:'):
        revision = line.partition(':')[1].strip()
        break

关于python - 使用子进程的 PIPE 时如何以字符串形式获取 python 对象 <class '_io.TextIOWrapper' > 的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32411035/

相关文章:

python-3.x - 使用 vtk 和 k3d 在 jupyter notebook 中渲染 gltf/glb 文件

python-3.x - PyTorch 不能使用 float 类型,只能使用 long

Python-导入错误: No module named 'vector'

python - 分割字符串时丢失编码

python - 如何使用 pandas 为数据框的一列中单独包含的每个时间添加 timedelta?

Python 包装。指定多次发布后的python版本要求

python - 如何从 Django Channels 获取查询参数?

python - OpenCV - 仅绘制关键点使用python引用的对象

perl - 如何在 Perl 中禁用隐式解码 ("upgrading")?

java - OutputStreamWriter构造函数: how does the encoding work?