【问题标题】:Python fork process inside Jupyter NotebookJupyter Notebook 中的 Python fork 进程
【发布时间】:2020-10-06 16:51:56
【问题描述】:

我在 Jupyter 笔记本中运行以下代码:

import os

print("Start")
pid = os.fork()

if pid == 0:
    print("Child")
    os._exit(os.EX_OK)
else:
    print("Parent")
    
if pid != 0:
    # parent
    pid, status = os.waitpid(pid, 0)
    print("Done")

我每次都“几乎”得到以下输出:

儿童
开始
家长
完成

如何在“开始”之前打印“孩子”?几乎 10 次中有 9 次,我得到如上所示的输出。有时,我会发现直观的预期(“Start”首先打印,然后是“Parent”或“Child”,最后以“Done”结束)。

当我直接在控制台上运行相同的代码时,每次都会得到预期的结果:

开始
家长
儿童
完成

为什么我们会在 Jupyter 笔记本中看到这种特殊行为?以及如何避免这种情况?

【问题讨论】:

    标签: python python-3.x jupyter-notebook ipython fork


    【解决方案1】:

    看起来标准输出是块缓冲的,而不是行缓冲的。父“Start\n”正在输出缓冲区中等待。子“Child\n”在其自己的输出缓冲区中开始,但在退出时被刷新。您可以通过import sys;print(sys.stdout.isatty()) 进行验证。解决方法是经常冲洗

    print("Start", flush=True)
    

    或者如果您有多个要打印的东西,

    print("Foo")
    print("Bar")
    sys.stdout.flush()
    

    【讨论】:

    • 您的解决方案确实为我解决了问题!非常感谢 :-) 我将测试这个问题是否仅限于打印。
    • 这将取决于它的运行方式。我不经常使用jupyter,所以我不确定。但如果它通过%run 完成,它可能只是一个管道子进程,因此标准输出将被块缓冲。
    【解决方案2】:

    据我所知,目前没有办法避免这种情况。也许有一个启用的设置。您也可以尝试添加等待。在您打印孩子或父母等之前。希望这会有所帮助。

    这样睡:

    import time
     
    # Wait for 5 seconds
    time.sleep(5)
     
    # Wait for 300 milliseconds
    # .3 can also be used
    time.sleep(.300)
    

    我建议等待 0.5 毫秒到 1 秒

    【讨论】:

    • 你能告诉我你通过添加等待的建议吗?这也不会太武断,具体取决于我们应用多少延迟。
    • 感谢您的回复。我希望有其他方法可以解决这个问题,因为计时器的使用非常“hacky”。 (也就是说,如果没有其他人能够提供更直接的解决方案,我将求助于此)。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    • 2016-12-01
    • 2019-07-09
    • 2020-03-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    相关资源
    最近更新 更多