Блокнот Юпитер. Как направить вывод в определенную ячейку?

Есть ли способ указать выходную ячейку, в которой функция должна печатать свои выходные данные?

В моем конкретном случае у меня запущено несколько потоков, каждый из которых имеет регистратор. Выходные данные регистратора печатаются в любой работающей ячейке, мешая предполагаемому выводу этой ячейки. Есть ли способ заставить регистратор печатать, например, только на cell #1?

Я бы сказал, что проще использовать ipywidget и отправлять туда изменения регистратора. См.: Виджет вывода.

alex 04.07.2024 14:21

перенаправить логи в файл или отключить регистратор

pwoolvett 04.07.2024 17:11

Это общий вопрос; подробности не нужны. Как указано, у меня работает несколько потоков; Я хотел бы перенаправить их вывод в определенную ячейку, если это возможно. Меня не интересует использование файлов журналов. Я знаю, что могу записать все в файлы журналов, но я хочу, чтобы выходные данные печатались непосредственно в определенной ячейке.

alec_djinn 08.07.2024 11:44
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
5
3
214
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете использовать следующий подход:

  • Перенаправьте все сообщения журнала в корневом журнале (который вы получите, вызвав getLogger()) в QueueHandler, чтобы накопить сообщения журнала в queue.Queue.
  • В предполагаемой выходной ячейке запустите QueueListener , который обертывает StreamHandler. QueueListener, как следует из названия, будет прослушивать новые элементы в очереди регистрации. Он передаст новые элементы в StreamHandler, который их фактически распечатает.

Предполагая, что мы хотим напечатать ниже ячейки 1, это может выглядеть следующим образом:

# Cell 1
import logging, queue, threading, time
from logging.handlers import QueueHandler, QueueListener

log_queue = queue.Queue(-1)

logging.getLogger().addHandler(QueueHandler(log_queue))

listener = QueueListener(log_queue, logging.StreamHandler())
listener.start()

В ячейке 2 мы смоделируем некоторую деятельность:

# Cell 2
def log_activity_1():
    while True:
        logging.getLogger().warning("Activity 1")
        time.sleep(1)

threading.Thread(target=log_activity_1, daemon=True).start()

И аналогично в ячейке 3:

# Cell 3
def log_activity_2():
    while True:
        logging.getLogger().warning("Activity 2")
        time.sleep(2)

threading.Thread(target=log_activity_2, daemon=True).start()

Вывод будет происходить, по сути, в режиме реального времени, под ячейкой, содержащей вызов listener.start(), то есть в ячейке 1 (и только там) в нашем случае. Это будет выглядеть так, как и ожидалось: для каждого зарегистрированного «Действия 2» мы будем видеть зарегистрированное «Действие 1» попеременно и примерно в два раза чаще, поскольку мы спим 2 секунды в первом случае и 1 секунду во втором:

После завершения обработки мы можем остановить QueueListener (программно или вручную) с помощью listener.stop() — точнее, мы должны остановить прослушиватель таким образом, следуя его документации: если вы не вызовете [stop()] до выхода приложения , в очереди могут остаться записи, которые не будут обработаны.

Это не работает так, как я ожидал. В моем случае выходные данные по-прежнему отображаются в активной ячейке, а не в ячейке прослушивателя.

alec_djinn 12.07.2024 09:59

@alec_djinn Если вы говорите «это не работает», вы имеете в виду: (1) с моим кодом, опубликованным выше, без изменений или (2) с вашим собственным кодом, адаптированным, как предложено выше? Кроме того: вы говорите только о выходных данных журнала (которые должен обрабатывать приведенный выше код) или также об обычных выходных данных print() (которые код выше не обрабатывает)?

simon 12.07.2024 10:02

С вашим кодом. Я получаю вывод в активной ячейке, а не в ячейке прослушивателя.

alec_djinn 12.07.2024 10:06

Проверьте это asteboard.co/UbsIRLY7mklt.png

alec_djinn 12.07.2024 10:07

Спасибо, что поделились, попробую воспроизвести.

simon 12.07.2024 10:07

Как видите, как только я print() попадаю в другую ячейку, выходные данные логгера передаются в эту ячейку. Вместо этого оно должно было попасть в камеру слушателя.

alec_djinn 12.07.2024 10:08

Это странно. У меня не происходит. Возможно, это зависит от системы (что, я согласен, не было бы хорошим решением). Я здесь на Linux.

simon 12.07.2024 10:13

Я тоже на Linux. Но я использую ноутбук Jupyter, а не лабораторию. Возможно, это и есть виновник.

alec_djinn 12.07.2024 10:19

Я только что попробовал и в лаборатории, и в блокноте. Никакой разницы.

simon 12.07.2024 10:20

Я не знаю, тогда...

alec_djinn 12.07.2024 10:20

Я тоже не знаю, извини. Я также попробовал два браузера (Chromium и Firefox), и у меня оба работают. В таком случае, я думаю, вам следует оставить награду :)

simon 12.07.2024 10:22

Последняя попытка: может быть, это мешает вашей теме Jupyter? На скриншоте выше я видел, что вы использовали темный режим, но по умолчанию в Jupyter нет темного режима. Можете ли вы попробовать отключить темы/тему по умолчанию?

simon 12.07.2024 10:39

Сброс темы на стандартную ничего не изменил. Я бегу Jupyter Notebook 6.4.12. На какой версии вы находитесь?

alec_djinn 12.07.2024 12:00

Jupyter Notebook 7.2.1 здесь (на Python 3.11.9)

simon 12.07.2024 12:46

Я только что попробовал использовать блокнот Jupyter 6.4.12 (Python 3.9.19, Ipython 7.33.0) в Firefox. У меня все еще работает.

simon 12.07.2024 13:09

На новой установке работает. Я принял решение. Спасибо!

alec_djinn 12.07.2024 13:11

Так рад это слышать! Хотя очень странное явление. В любом случае: я рад, что в итоге все получилось!

simon 12.07.2024 13:12

Вы можете создать оболочку, которая будет перенаправлять все напечатанное в другую ячейку.

# Cell 1

import logging
from io import StringIO
from IPython.display import display, HTML
import sys

# Set up a StringIO object to capture output
output_capture = StringIO()
ch = logging.StreamHandler(output_capture)
ch.setLevel(logging.INFO)

# Configure the logger
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logger.addHandler(ch)

# Create a display area
display_id = display(HTML(''), display_id=True)

# Function to update the display
def update_display():
    output_contents = output_capture.getvalue()
    display_id.update(HTML(f"<pre>{output_contents}</pre>"))

def capture_output(func):
    def wrapper(*args, **kwargs):
        # Redirect stdout to our StringIO object
        old_stdout = sys.stdout
        sys.stdout = output_capture
        
        try:
            # Call the original function
            result = func(*args, **kwargs)
        finally:
            # Restore stdout
            sys.stdout = old_stdout
            
        # Update the display
        update_display()
        
        return result
    return wrapper

В следующей ячейке:

# Cell 2
@capture_output
def my_function():
    print('Hello world!')

# Now when you call my_function(), anything printed within the function will be displayed in the first cell
my_function()

Это красивое решение, но оно не работает, когда функция сталкивается с потоками. Это требование.

alec_djinn 12.07.2024 09:41

Другие вопросы по теме

Добавьте «журнал» для одной функции
Регистратор Serilog, использующий var logger, ничего не выводит ни на консоль, ни в файл
Невозможно использовать дополнительный атрибут с помощью специального средства форматирования в Python с модулем ведения журнала
Azure WebApp LogStream отображает один и тот же журнал несколько раз и отображает все журналы как [ОШИБКА], даже если они имеют уровень [INFO]
Как я могу получить полные журналы усеченной строки base64 из Xcode?
Как удалить дублирование исправлений логгера loguru в pytest
Запись в файл завершается сбоем в средстве журнала пакетов R, если вызывается изнутри функции
Как отправлять структурированные журналы в стек ELK с настраиваемыми полями с помощью ведения журнала Python?
Окно журнала .net MAUI с несколькими текстовыми выводами
Написание сценария оболочки для извлечения журналов в указанную временную метку