Что нужно, чтобы разместить живую фигуру Matplotlib в посте?

Я знаю, что это выходит за рамки возможностей большинства сообществ, но мы — научное сообщество, использующее Python и множество графиков (Matplotlib), которыми мы обмениваемся друг с другом через Discourse.

Было бы потрясающе иметь возможность делиться интерактивными графиками вместо статических JPG/PNG.

Рассмотрим этот пример:

import matplotlib.pyplot as plt
import mpld3
import numpy as np

Fs = 4000
f = 100
sample = 200
x = np.arange(sample)
y = np.sin(2 * np.pi * f * x / Fs)
fig, ax = plt.subplots(1,1)
ax.plot(x, y, marker=".")
html_str = mpld3.fig_to_html(fig)
Html_file= open("index.html","w")
Html_file.write(html_str)
Html_file.close()

Вы сможете открыть файл index.html, и он покажет это (только что он будет ИНТЕРАКТИВНЫМ…)

Так что, мне кажется, мы уже на полпути, верно?
Может быть, достаточно просто загружать HTML-файл, чтобы он запускался в каком-либо iframe?

Описанный вами метод был бы возможен с помощью пользовательского плагина, объединяющего плагин в стиле markdown-it и, возможно, удобное хранилище объектов для HTML-файлов. Однако я бы проявил осторожность в вопросах безопасности, позволяя выполнять код, введённый пользователем, в любой части сервера. Discourse уже проделывает большую работу, чтобы обезопасить посты от HTML и JS для безопасного разбора на стороне сервера.

Возможно, вам лучше попробовать внедрить интерпретатор Python прямо в браузер и запускать код на стороне клиента, минуя весь процесс создания HTML. JupyterLite позволит запускать JupyterLab в браузере с интерфейсом. Согласно документации, можно настроить автоматическое выполнение кода при создании iframe. Вы можете передавать код с помощью пользовательского плагина HighlightJS, который создаст интерактивную кнопку для любого блока кода Python, или настроить автоматический запуск.

Таким образом, процесс будет выглядеть так:

  1. Пользователь видит пост с блоком кода Python.
  2. При наведении курсора на блок кода появляется кнопка, позволяющая запустить код в браузере.
  3. Пользователь нажимает на кнопку, что создаёт iframe с JupyterLite под блоком кода и импортирует код из этого блока.

Поскольку это будет просто плагин HighlightJS, создающий iframe для JupyterLite, всё можно реализовать в рамках компонента темы, без необходимости написания серверного кода.

Одно замечание: JupyterLite описывается как не полностью соответствующий JupyterLab, и я не уверен, как он обрабатывает импорт пакетов, поэтому, возможно, вам придётся размещать его самостоятельно. JupyterLite использует Pyodide, который поддерживает любые wheel-пакеты из PyPI, поэтому проблем быть не должно.

Я считаю, что риск для безопасности не так велик, если index.html выполняется на стороне клиента (в браузере пользователя, а не на сервере Discourse).

Кроме того, преимущество подхода mpld3 заключается в том, что это один файл без зависимостей. Если вы запускаете сырой Python, вам также нужно иметь возможность загружать все зависимости, такие как CSV-файлы, файлы данных и т. д., которые являются источником данных для построения графиков.

Тем не менее, возможность запускать сырые скрипты Python внутри поста Discourse была бы просто восхитительной!

Ой! Я полностью неправильно понял, как будет генерироваться HTML. Если пользователь заранее генерирует HTML, вы можете предложить ему встроить его через iframe с внешнего сайта, предварительно добавив домен в белый список.

Например, CodePen, который должен быть разрешён по умолчанию:

<iframe height="300" width="800" style="width: 100%;" scrolling="no" title="mplD3 example, actually working" src="https://codepen.io/gully/embed/BawMGr?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href="https://codepen.io/gully/pen/BawMGr">
  mplD3 example, actually working</a> by gully (<a href="https://codepen.io/gully">@gully</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>

Это абсолютно возможно:

Если у вас много пользователей, вам может потребоваться помощь в автоматизации части настройки.

Я могу помочь, если у вас есть бюджет.

Это действительно здорово!
У меня есть несколько вопросов:

  1. Как вы думаете, это будет работать с ipympl? (Иначе графики не будут интерактивными, что лишает весь смысл)
  2. Как вы думаете, это можно будет использовать с базовой папкой проекта, где мы сможем установить переменную окружения PYTHONPATH перед запуском Jupyter, чтобы пользователи могли импортировать функции и зависимости из подключенного проекта?

И да, у меня есть бюджет, если это разумно и осуществимо, и если это можно будет внести как открытое исходное решение для всего сообщества Discourse.

Очень вероятно.

Я вижу способ создать совместную среду.

Не стесняйтесь написать мне в личные сообщения — мы можем обсудить это в ходе звонка.

@Alteras Спасибо, это решение действительно простое и работает, если вы найдете способ загрузить файл “index.heml” на Discourse (что легко сделать, разрешив загрузку .html) и отобразить его в коде iframe. Единственная проблема в том, что на самом деле это не работает… когда я пытаюсь это сделать, файл просто скачивается вместо того, чтобы отображаться в iframe. Возможно, существует мета-тег, который скажет iframe показывать файл, а не скачивать его?

Ах, понятно. По умолчанию Discourse устанавливает для всех вложений, не являющихся изображениями, заголовок Content-Disposition со значением «attachment», что заставляет браузер воспринимать их только как файлы для загрузки.

Вы можете попробовать что-то похожее на предварительный просмотр PDF-файлов в тексте, который, похоже, решает эту же проблему, но для загружаемых PDF-документов.