我想在python中分叉一个不运行外部命令的子进程...它只会运行一个定义的函数。我想分别捕捉stdout
和stderr
。
我知道如何使用os.fork()
和os.pipe()
,但这种机制只给了我两个fd。我正在寻找三个 fd:一个用于stdin
,一个用于stdout
,一个用于stderr
。在运行外部命令时,使用 subprocess.Popen
很容易管理,但该函数似乎不允许分叉本地函数;只有一个单独的可执行文件。
在 ruby 中,popen3
命令可以采用 "-" 作为其命令参数,在这种情况下,在没有调用任何外部命令的情况下进行分叉,并且返回我提到的 3 个 fd。在 python 中是否有某种 python 模拟这个例程?
stdout
和stderr
与子进程分开重定向,只需为每个管道创建两个单独的管道,而不是一个管道。我已经分享了相关的代码。您还可以阅读此线程以获取有关此主题的更多知识: 将标准输出重定向到 Python 中的文件?
我已经提到了两种写入 stdout 的方法,以及来自子进程的 stderr(
Method1
、Method2
如果还想写入子进程的 stdin,则应创建另一个文件描述符。这一次,
r
将转到子进程,w
将转到父进程。
import os
import sys
import time
# Create two pipes. One for sys.stdout, and one for sys.stderr
r_out, w_out = os.pipe()
r_err, w_err = os.pipe()
pid = os.fork()
if pid == 0:
# Child process
os.close(r_out)
os.close(r_err)
w1 = os.fdopen(w_out, "w")
w2 = os.fdopen(w_err, "w")
sys.stdout = w1
sys.stderr = w2
# Note that flush=True is necessary only if you want to ensure the order of messages printed
# across method1, and method2 is maintained
# Method 1: Standard Python print messages
print("Redirected to stdout #2", flush=True)
print("Redirected to stderr #2", file=sys.stderr, flush=True)
# Method 2: Using system file descriptors
stdout_fd = sys.stdout.fileno()
os.write(stdout_fd, b'Redirected to stdout')
stderr_fd = sys.stderr.fileno()
os.write(stderr_fd, b'Redirected to stderr')
# Restore original stdout, and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
# Close the file descriptors
w1.close()
w2.close()
else:
# Parent process
os.close(w_out)
os.close(w_err)
r1 = os.fdopen(r_out)
r2 = os.fdopen(r_err)
for i in range(5):
# Note that r1.read(), and r2.read() are non-blocking calls
# You can run this while loop as long as you want.
print("Read text (sysout):", r1.read())
print("Read text (syserr):", r2.read())
time.sleep(0.5)