【问题标题】:Callback function to process output处理输出的回调函数
【发布时间】:2014-12-30 11:08:17
【问题描述】:

最近我一直在玩Popen。我在后台生成了一个进程,将输出写入TemporaryFile

f = tempfile.TemporaryFile()
p = subprocess.Popen(["gatttool"], stdin = subprocess.PIPE, stdout = f)

现在它的工作方式是我通过stdin 向进程发送命令并稍后读取临时文件。而且它是非阻塞的,所以我可以执行其他任务。

问题是gatttool 有时会自己生成一些输出字节(例如通知)。我正在寻找一种在不阻塞TemporaryFile的情况下读取此输出的方法。

我的问题:

1) 从TemporaryFile(50 行)读取输出并希望subprocess 优雅地等待我读取该数据是否安全,或者它会终止吗?

2) 有没有一种优雅的方法来创建一个回调函数,该函数将在TemporaryFile 上的每个事件上调用(而不是让一个线程每秒运行一次并读取数据)?

【问题讨论】:

  • 看起来是命名管道(而不是普通文件)的一个很好的用例。
  • 也许:docs.python.org/2.2/lib/os-fd-ops.html 并简单地使用 pipe() ?
  • 就我个人而言,我喜欢在子进程周围使用更高级别的包装器,例如 sh 模块 - 这就是为什么我发布 cmets 而不是编写正确答案的原因。
  • 1) 是什么让您认为从f 文件读取对子进程有任何影响?你在 Windows 上吗? 2)有文件系统监控工具,但它是XY problem。如果gatttool 产生新行,您是否希望收到通知(例如,通过回调)?
  • 实际上我已经找到了解决方案,您可以创建一个管道,gatttool 在一端推送数据,而在另一端您只需接收数据。似乎暂时有效

标签: python subprocess communication temporary-files


【解决方案1】:

其实解决方法很简单。创建一个pipe,使用gatttool 输出作为输入。该管道的输出转到thread,它逐行读取该输出,并解析每一行。检查它,它的工作原理。请锁定这个问题。

# Create a pipe. "gatt_in" ins where the "gatttool" will be dumping it's output.
# We read that output from the other end of pipe, "gatt_out"
gatt_out, gatt_in = os.pipe()

gatt_process = subprocess.Popen(["gatttool", "your parametres"], stdin = subprocess.PIPE,
                                stdout = gatt_in)

现在每次我想向gatttool 发送命令时,我都会这样做:

gatt_process.stdin.write("Some commands\n")

此命令的结果将出现在gatt_out 中。就我而言,这是在另一个线程中处理的。

【讨论】:

  • 你的意思是stdout=subprocess.PIPE
  • 你能发布你用来做这个的代码吗?我是 Python N00b,非常感谢看到这段代码。我遇到了同样的问题。
  • 投反对票。使用stdout=subprocess.PIPE 而不是os.pipe()
  • 使用 stdout=subprocess.PIPE 阻止应用程序执行,这就是我想要避免的
  • PIPE 在 POSIX 系统上以 os.pipe 的形式实现。如果它阻塞了,那么您的解决方案也会阻塞。
【解决方案2】:

要从子进程提供输入/获取输出,您可以使用subprocess.PIPE

from subprocess import Popen, PIPE

p = Popen(['gatttool', 'arg 1', 'arg 2'], stdin=PIPE, stdout=PIPE, bufsize=1)
# provide input
p.stdin.write(b'input data')
p.stdin.close()
# read output incrementally (in "real-time")
for line in iter(p.stdout.readline, b''):
    print line,
p.stdout.close()
p.wait()

【讨论】:

  • 使用PIPE 作为标准输出会导致应用程序挂起。 gatttool 不发送 EOF,它只是坐在那里。此外,在您的示例中,您只提供单行数据,而在我的应用程序中,我提供了一些输入,输出收集在其他地方
  • @Melon:显然,您可以写多行(调用p.stdin.write)并且您不需要在同一个线程中读取:您可以将读取循环放入守护线程并调用每行/字节/任何你喜欢的回调。在内部,subprocess 模块可以使用os.pipe(),这样你就不需要自己调用了。
猜你喜欢
  • 2013-06-24
  • 1970-01-01
  • 1970-01-01
  • 2018-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多