将分叉 python 进程的输出重定向到管道
Redirect output of forked python process to pipe
我想将一些已记录的进程从分叉的 Python 进程写入父进程,因此我为此使用了管道对:
rpipe, wpipe = os.pipe()
pid = os.fork()
if pid == -1:
raise TestError("Failed to fork() in prepare_test_dir")
if pid == 0:
# Child -- do the copy, print log to pipe and exit
try:
os.close(rpipe)
os.dup2(wpipe, sys.stdout.fileno())
os.dup2(wpipe, sys.stderr.fileno())
os.close(wpipe)
self._prepare_test_dir(test)
sys.stdout.write(self.copy_log)
finally:
os._exit(1)
os.close(wpipe)
_, status = os.waitpid(pid, 0)
# XXX: if copy_log is larger than PIPE_BUF (4-8k), everything
# then is going badly
outf = os.fdopen(rpipe)
self.copy_log = outf.read()
return os.WEXITSTATUS(status)
它不起作用,self.copy_log
中什么也没有出现。我还尝试使用 fdopen
:
显式构造 stdout 对象
sys.stdout = os.fdopen(wpipe, 'w')
也不行。但是,如果我将 print
放在 dup2
之前:
if pid == 0:
try:
print 'HELLO'
os.close(rpipe)
os.dup2(wpipe, sys.stdout.fileno())
os.dup2(wpipe, sys.stderr.fileno())
...
复制日志成功传递给父级并且'HELLO'打印到控制终端。我认为 print
会以某种方式影响 sys.stdout
(通过延迟初始化或其他方式)。有什么想法吗?
我在各种 Linux 平台上使用 Python 2.6 和 2.7。
问题似乎不在 pipe/dup2 相关代码中,而是在 os._exit
中。这是杀死 python 解释器的残酷方法(但对于分叉进程是可以的,因此它不会触及 "shared" 对象),但它会导致 stdout
和 stderr
不被刷新, 数据丢失。
我在 child 中得到了以下代码:
try:
os.close(rpipe)
os.dup2(wpipe, sys.stdout.fileno())
os.dup2(wpipe, sys.stderr.fileno())
os.close(wpipe)
print 'aaaaaaaaa'
except:
traceback.print_exc(20, sys.stderr)
finally:
sys.stdout.flush()
sys.stderr.flush()
os._exit(1)
我想将一些已记录的进程从分叉的 Python 进程写入父进程,因此我为此使用了管道对:
rpipe, wpipe = os.pipe()
pid = os.fork()
if pid == -1:
raise TestError("Failed to fork() in prepare_test_dir")
if pid == 0:
# Child -- do the copy, print log to pipe and exit
try:
os.close(rpipe)
os.dup2(wpipe, sys.stdout.fileno())
os.dup2(wpipe, sys.stderr.fileno())
os.close(wpipe)
self._prepare_test_dir(test)
sys.stdout.write(self.copy_log)
finally:
os._exit(1)
os.close(wpipe)
_, status = os.waitpid(pid, 0)
# XXX: if copy_log is larger than PIPE_BUF (4-8k), everything
# then is going badly
outf = os.fdopen(rpipe)
self.copy_log = outf.read()
return os.WEXITSTATUS(status)
它不起作用,self.copy_log
中什么也没有出现。我还尝试使用 fdopen
:
sys.stdout = os.fdopen(wpipe, 'w')
也不行。但是,如果我将 print
放在 dup2
之前:
if pid == 0:
try:
print 'HELLO'
os.close(rpipe)
os.dup2(wpipe, sys.stdout.fileno())
os.dup2(wpipe, sys.stderr.fileno())
...
复制日志成功传递给父级并且'HELLO'打印到控制终端。我认为 print
会以某种方式影响 sys.stdout
(通过延迟初始化或其他方式)。有什么想法吗?
我在各种 Linux 平台上使用 Python 2.6 和 2.7。
问题似乎不在 pipe/dup2 相关代码中,而是在 os._exit
中。这是杀死 python 解释器的残酷方法(但对于分叉进程是可以的,因此它不会触及 "shared" 对象),但它会导致 stdout
和 stderr
不被刷新, 数据丢失。
我在 child 中得到了以下代码:
try:
os.close(rpipe)
os.dup2(wpipe, sys.stdout.fileno())
os.dup2(wpipe, sys.stderr.fileno())
os.close(wpipe)
print 'aaaaaaaaa'
except:
traceback.print_exc(20, sys.stderr)
finally:
sys.stdout.flush()
sys.stderr.flush()
os._exit(1)