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.