从python子进程中的fd#3读取

时间:2013-04-09 19:27:10

标签: python debian subprocess

我正在为Debian的debootstrap实用程序编写一个python前端。 Debootstrap可以输出进度信息,但如果是file descriptor #3 is open, and it writes to this fd,则会输出。

我找到了some hints,但我无法理解如何在Python中使用它。

如何在Python中创建fd#3,运行debootstrap子进程并从fd#3读取?

2 个答案:

答案 0 :(得分:1)

我认为您需要使用低级操作系统API在fd 3上设置管道,例如:

import os, sys

# No other fds have been opened, so the lowest available are used (3, 4)
read, write = os.pipe()

# We want the child to write into fd#3, but right now that's the read
# end of the pipe, so do a little switching around:
temp = os.dup(read)
os.dup2(write, read)
os.dup2(temp, write)
os.close(temp)
read, write = write, read # swap actual values to avoid confusion

pid = os.fork()
if pid == 0: # child
   os.close(read)
   try:
       os.execl('/bin/bash', 'bash', '-c', 'echo testing...>&3')
   except OSError:
       sys.exit(1)
else: # parent
   os.close(write)
   progress = os.fdopen(read)
   print progress.read()
   os.wait()

基本上,创建管道,并交换读/写端,以便写入结束在fd#3上(将使用最低可用fds,所以请确保您还没有打开任何其他fds。)

然后,在父和子中分叉并关闭适当的管道末端。然后我们可以在孩子中执行目标,在我的例子中,我使用bash作为例子。在父级中,我们可以在管道的读取端周围构建一个类似于文件的普通对象,并继续使用它而不必担心低级API。

如果在管道的读取端设置subprocess,则可以使用FD_CLOEXEC模块,但是您仍然需要进行低级调用来设置管道,所以这样做没什么好处。

答案 1 :(得分:0)

这是:

import os, sys

read, write = os.pipe()

pid = os.fork()
if pid == 0: # child
   os.close(read)
   os.dup2(write, 3)
   os.close(write)
   try:
       os.execl('/bin/bash', 'bash', '-c', 'for f in 1 2 3 4 5 6 7 8; do echo testing...>&3; sleep 1; done')
   except OSError:
       sys.exit(1)
else: # parent
   os.close(write)
   progress = os.fdopen(read)
   while True:
       l = progress.readline()
       if l:
           print l
       else:
           break