#python #python-3.x #jupyter-notebook #ipython #fork
#python #python-3.x #jupyter-notebook #ipython #форк
Вопрос:
Я запускаю следующий код внутри ноутбука 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")
Я получаю следующий вывод «почти» каждый раз:
Дочерний
запуск
родительского
элемента завершен
Как получается, что «Дочерний элемент» печатается перед «запуском»? Почти в 9 из 10 раз я получаю результат, как указано выше. Иногда я нахожу то, что интуитивно ожидается (сначала печатается «Start», затем «Parent» или «Child», а затем, наконец, заканчивается «Done»).
Когда я запускаю один и тот же код непосредственно на консоли, я каждый раз получаю ожидаемый результат:
Запуск
родительского
дочернего
элемента завершен
Почему мы видим это странное поведение в Jupyter Notebook? И как этого избежать?
Ответ №1:
Похоже, что стандартный вывод буферизуется по блокам, а не по строкам. Родительский «Start n» ожидает в выходном буфере. Дочерний элемент «Child n» запускается в своем собственном выходном буфере, но сбрасывается при выходе. Вы могли бы проверить с import sys;print(sys.stdout.isatty())
помощью . Решение состоит в том, чтобы часто очищать
print("Start", flush=True)
или, если у вас есть несколько вещей для печати,
print("Foo")
print("Bar")
sys.stdout.flush()
Комментарии:
1. Ваше решение, безусловно, исправило порядок для меня! Большое спасибо 🙂 Я собираюсь проверить, связана ли эта проблема с печатью.
2. Это будет зависеть от того, как он выполняется. Я не часто использую jupyter, поэтому я не уверен. Но если это сделано через
%run
, это может быть просто конвейерный подпроцесс, поэтому стандартный вывод будет буферизован по блокам.
Ответ №2:
На данный момент я не знаю способа избежать этого. Возможно, есть параметр, который включен. Вы также можете попробовать добавить ожидание. Перед печатью дочернего или родительского элемента и т. Д. Надеюсь, это немного поможет.
Спите так:
import time
# Wait for 5 seconds
time.sleep(5)
# Wait for 300 milliseconds
# .3 can also be used
time.sleep(.300)
Я бы предложил подождать от .5 миллисекунд до 1 секунды
Комментарии:
1. Не могли бы вы показать мне, что вы предлагаете, добавив wait? Также не будет ли это слишком произвольным в зависимости от конкретного случая о том, какую задержку мы применяем.
2. Спасибо за ваш ответ. Я надеюсь, что есть какой-то другой способ преодолеть эту проблему, поскольку использование таймеров очень «хакерское». (Тем не менее, если никто другой не сможет предложить более простое решение, я прибегну к этому). Спасибо.