2025, Oct 31 12:18

Запуск pandas и yfinance в PyScript: почему SMA не работает в браузере и что делать

Почему в PyScript в браузере ломаются pandas и yfinance при расчёте SMA: ImportError и CORS. Даем решение: py-config для pandas и серверный эндпоинт для данных.

Запуск pandas и yfinance в браузере с PyScript: почему ваш демо-пример с SMA ломается и как это исправить

Построить калькулятор Simple Moving Average прямо в браузере на PyScript кажется делом очевидным: взять ввод пользователя со страницы, получить рыночные данные через yfinance, посчитать скользящее среднее в pandas и отрисовать результат. На деле вы быстро упрётесь в ImportError для pandas, а затем — в ещё более жёсткое ограничение с yfinance в браузере. Разберёмся, что происходит и какая архитектура действительно работает.

Минимальный пример, который не работает

Ниже — фрагмент, повторяющий исходную идею: HTML-поля для тикера, диапазона дат и окна; затем блок PyScript, который забирает значения и считает SMA в pandas после загрузки цен через yfinance.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <script type="module" src="https://pyscript.net/releases/2024.2.1/core.js"></script>
  <title>SMA Demo</title>
</head>
<body>
  <form>
    <label for="symField">Enter ticker symbol:</label>
    <input type="text" id="symField" />
    <br />
    <label for="fromDate">Enter start date:</label>
    <input type="datetime" id="fromDate" />
    <br />
    <label for="toDate">Enter end date:</label>
    <input type="datetime" id="toDate" />
    <br />
    <label for="spanDays">Enter number of trading days (window) for SMA:</label>
    <input type="number" id="spanDays" />
    <br />
    <button type="button" id="btnGo">Calculate SMA</button>
    <button type="button" id="btnReset">Refresh</button>
  </form>
  <py-script>
from pyodide import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import yfinance as yf
sym_el = Element('symField').element
start_el = Element('fromDate').element
stop_el = Element('toDate').element
frame = yf.download(sym_el, start=start_el, end=stop_el)
win_el = Element('spanDays').element
frame['Simple Moving Aberage'] = frame['Close'].rolling(window=win_el).mean()
print(frame)
  </py-script>
</body>
</html>

В браузере такая схема приводит к ошибке вида:

ImportError: cannot import name 'pandas' from 'pyodide'

Что на самом деле ломается и почему

Есть две независимые проблемы. Во‑первых, строка импорта pandas неверна для PyScript. Нельзя импортировать pandas из pyodide; пакет нужно объявить в конфигурации PyScript, а затем импортировать обычным способом. Это легко исправить.

Вторая проблема — архитектурная и в браузере непреодолима: yfinance зависит от requests, а попытка заменить его на fetch упирается в CORS. Иначе говоря, yfinance нельзя использовать непосредственно в браузерном окружении. Даже если вы решите вопрос с pandas, yfinance на стороне клиента работать не будет из‑за этих ограничений. PyScript не предоставляет обходного пути под обозначенные требования.

Что реально исправить в браузере: pandas через py-config

Сделать pandas доступным для PyScript можно, объявив его в конфигурационном блоке и импортировав как обычно. Рабочий шаблон выглядит так; полноценный пример есть в этом примере PyScript.

<py-config>
    name = "Pandas"
    description = "A simple application that loads a csv and displays a table of its contents."
    packages = ["pandas"]
</py-config>
<py-script>
import pandas as pd
# ваша логика на pandas — здесь
</py-script>

Перенося это на страницу с SMA, браузерную часть можно переоформить так, чтобы корректно подключить pandas и сохранить логику для последующей интеграции. Обратите внимание: yfinance остаётся в коде для полноты картины, но в браузере он не выполнится.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <script type="module" src="https://pyscript.net/releases/2024.2.1/core.js"></script>
  <title>SMA Demo (Fixed pandas import)</title>
</head>
<body>
  <py-config>
    name = "Pandas"
    description = "Enable pandas in PyScript"
    packages = ["pandas"]
  </py-config>
  <form>
    <label for="symField">Enter ticker symbol:</label>
    <input type="text" id="symField" />
    <br />
    <label for="fromDate">Enter start date:</label>
    <input type="datetime" id="fromDate" />
    <br />
    <label for="toDate">Enter end date:</label>
    <input type="datetime" id="toDate" />
    <br />
    <label for="spanDays">Enter number of trading days (window) for SMA:</label>
    <input type="number" id="spanDays" />
    <br />
    <button type="button" id="btnGo">Calculate SMA</button>
    <button type="button" id="btnReset">Refresh</button>
  </form>
  <py-script>
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import yfinance as yf
sym_el = Element('symField').element
start_el = Element('fromDate').element
stop_el = Element('toDate').element
frame = yf.download(sym_el, start=start_el, end=stop_el)
win_el = Element('spanDays').element
frame['Simple Moving Aberage'] = frame['Close'].rolling(window=win_el).mean()
print(frame)
  </py-script>
</body>
</html>

То, чего нельзя сделать в браузере: yfinance

Зависимость yfinance от requests не позволяет запускать его в браузере, а вариант с fetch блокируется CORS. Поэтому получение рыночных данных нужно вынести с клиента. Практичный путь — небольшой сервер на веб‑фреймворке, например Flask, который выполняет загрузку данных и затем отдаёт результат на фронтенд. В таком окружении yfinance можно использовать на сервере без браузерных ограничений.

Почему это важно для архитектуры и инструментов

Вывод здесь не только про исправление импорта pandas, а про рамки возможностей PyScript. Пакеты, завязанные на сетевые стеки, несовместимые с браузером, на клиенте не запустятся, а CORS блокирует произвольные попытки обратиться к тем же конечным точкам через fetch. Понимание этих ограничений заранее помогает спланировать аккуратное разделение: получение данных и вычисления — на сервере; интерактивность и визуализация — в браузере. PyScript остаётся полезным для Python в браузере, если пакеты совместимы, но это не универсальная замена серверным задачам.

Итоги

Включайте pandas в PyScript через блок py-config и обычный import — это будет работать, как показано в официальном примере. Не пытайтесь запускать yfinance в браузере: вынесите получение рыночных данных в лёгкий серверный эндпоинт на веб‑фреймворке и передавайте результат на фронтенд для визуализации. Такое разделение уважает ограничения безопасности браузера и делает ваш процесс расчёта SMA стабильным и удобным в сопровождении.

Статья основана на вопросе на StackOverflow от rashmip_21 и ответе Detlef.