如何在使用os.execl替换进程时重定向stdin / stdout / stderr

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在使用os.execl替换进程时重定向stdin / stdout / stderr相关的知识,希望对你有一定的参考价值。

请考虑以下示例脚本:

import os
import sys

print(1)
os.execl(sys.executable, sys.executable, '-c', 'print(2)')
print(3)

结果是

1

我在期待

1
2

我认为这是因为替换过程不使用相同的stdin / stdout / stderr?

在使用execl时,如何实现我期望的效果?

我在Windows上使用Python 3.6。

答案

这不是关于PyCharm的错误,因为我无法用IDEA重现它。 IDEA正在使用与PyCharm相同的核心。

这是因为您启动脚本的方式。如果您使用Run启动脚本,它可以正常工作。如果你用Debug启动它,它不会。

因为Run只是在终端中运行脚本,但Debug将启动调试器并将该进程连接到此调试器。您看到的输出实际上来自调试器,但不是直接来自您的脚本。替换进程时,调试器不会重建与新创建进程的连接。

这就是为什么你没有得到2输出。

另一答案

在Linux中,有一个标志FD_CLOEXEC,你可以通过fcntl.fcntl(sys.stdout,fcntl.F_GETFD)测试它

您描述的行为可以在ubuntu16中重现

import os
import sys
import fcntl
print(1)
ret = fcntl.fcntl(sys.stdout, fcntl.F_GETFD)
ret |= fcntl.FD_CLOEXEC
fcntl.fcntl(sys.stdout, fcntl.F_SETFD, ret)
os.execl(sys.executable, sys.executable, '-c', 'print(2)')
print(3)

因此,当您在PyCharm中运行时,它必须重定向标准输出并设置等效的Windows标志。

以上是关于如何在使用os.execl替换进程时重定向stdin / stdout / stderr的主要内容,如果未能解决你的问题,请参考以下文章

如何仅在确切的 url 匹配时重定向?

如何在通知点击时重定向到特定的 ViewController?

在 Django 中,如何在提交 CreateView 时重定向到 UpdateView?

Django - 如何在发送邮件时重定向

滚动时重定向到*新页面* - 如何添加时间延迟?

Angular:如何在提交时重定向到另一个页面