【问题标题】:Python3 Popen: Do I have to use .encode() every time?Python3 Popen:我每次都必须使用 .encode() 吗?
【发布时间】:2016-11-04 20:50:48
【问题描述】:

我有一个用于测试另一个程序的程序。它像这样使用 Popen:

testProgram = subprocess.Popen(args, stdin = subprocess.PIPE, stdout = subprocess.PIPE)

在 python2 中,我向testProgram 发送指令,如下所示:

testProgram.stdin.write("count "+vals[0]+"\n")

在 python3 中,write 需要一个类似字节的对象而不是 str。我认为这需要我在每次写入时使用testProgram.stdin.write(("count "+vals[0]+"\n").encode("utf-8")) 之类的东西,但我显然不会这样做。

有没有一种简单的方法可以让 Popen 的标准输入在 python3 中作为文本流工作,还是我应该坚持使用 python2? 参数universal_newlines = True looks like it should work,但对我来说,程序只是冻结在result = testProgram.stdout.readline()

【问题讨论】:

  • 程序是什么,你在输入什么?
  • 这是一个“事件计数器”。我真的不知道这意味着什么,但我知道它应该做什么。它应该从文件中读取 AVL 树,然后检查标准输入以获取更多说明。该脚本输入了几千条指令,并确保条目正确,并且树的大小不会增长到超出必要的范围。
  • universal_newlines = True 应该可以工作,所以我唯一想到的是可能存在一些编码问题docs.python.org/3.2/library/…
  • 那我可能问错问题了。如果universal_newlines = true 是正确答案,那么关于result = testProgram.stdout.readline() 的某些内容是不正确的。

标签: string python-3.x pipe subprocess


【解决方案1】:

使用universal_newlines=True 是正确的解决方案,但在python3 中,输入不会自动刷新每个换行符,除非您将bufsize=1 传递给Popen。

为了让程序在python3中运行,Popen这一行变成了:

testProgram = subprocess.Popen(args, stdin = subprocess.PIPE, stdout = subprocess.PIPE, universal_newlines = True, bufsize = 1)

【讨论】:

  • for line in testProgram.stdout 也应该这样做
  • 1- 如果 universal_newlines=True 在您的情况下不够用,您可以使用 io.TextIOWrapper() 包装二进制流 2- 您可以使用 print("count", vals[0], file=testProgram.stdin, flush=True) 刷新标准输入缓冲区(bufsize=1 可能会被忽略在旧的 Python 3 版本上)。通常,您应该组织脚本以同时使用 stdin/stdout 管道(使用线程或 async.io),否则可能会发生死锁,除非您对 stdin 的写入与从 stdout 的读取不完全同步(这是非常易碎)
  • @J.F.sebastian 很高兴知道bufsize=1 在旧版本中不起作用。至于并发,我不明白为什么这里需要它。我向标准输入写了一些东西,子进程得到它,确实工作,并将一些东西放入标准输出。读取标准输出是阻塞的,所以子进程需要多长时间才能给出输出似乎并不重要;程序将等待它。
  • @PadraicCunningham for line in x.stdout 不好。它会尝试读取所有内容,直到到达 EOF。
  • @Kenkron 如果您不知道何时停止读取标准输出,那么如果您不同时读取/写入管道,则可能会发生死锁:您的父脚本可能会被阻止读取标准输出,而子进程同时等待下一个输入——死锁。如果您知道何时停止阅读:这是我在上面所说的“完全同步”的情况(它可能有效,但对于意外输出非常脆弱,例如,由于测试中可能出现的一些错误)。如果您只需要传递一次输入,然后读取标准输出直到 EOF,那么只需使用 output = process.commmunicate(input_data)[0]
猜你喜欢
  • 1970-01-01
  • 2020-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多