Hace un tiempo vimos como hacer un panel de control con tecnología web usando streamlit pero usando Python en lugar de HTML, CSS y/o javascript. Streamlit es una biblioteca que te permite hacer aplicaciones de datos de forma sencilla y, a pesar de que tiene limitaciones evidentes, puede ser tremendamente útil para muchos casos.
Al final de ese artículo puse un P.D. indicando que intenté hacerlo funcionar con MyBinder para que cualquiera lo pudiera probar en vivo sin necesidad de instalarse nada pero fallé estrepitosamente.
Muy bien, pero, ¿qué es MyBinder?
MyBinder permite ejecutar Jupyter notebooks que se encuentran alojados en repositorios en Github, gitlab, figshare, zenodo,… Esta infraestructura es ideal para probar ciertos códigos, conjuntamente con sus datos y todo lo necesario para ejecutarlos (bibliotecas y demás), sin necesidad de tener nada instalado en el PC local.
Esta infraestructura ha ido evolucionando y ahora en MyBinder se pueden llegar a ejecutar cosas muy variopintas como:
- un escritorio linux: puedes ver, por ejemplo, la posibilidad de ejecutar aplicaciones de escritorio con Qt y Python de nuestro curso.
- JupyterLab.
- Shiny.
- PostgreSQL
- …
Para hacer que un repositorio funcione en MyBinder tenemos que prepararlo para ello. La forma más básica es usando un fichero de configuración que incluimos en el repositorio. Este fichero de configuración puede ser un fichero environment.yml que instalará un entorno conda. Podemos usar otra serie de cosas, algunas de forma conjunta, como luego veremos. Lo mejor es leer la documentación de Binder para entender cómo funciona todo.
Problemas que me encontré anteriormente
Como he comentado más arriba, en el anterior artículo de streamlit
me encontré varios problemas para hacerlo funcionar en MyBinder:
- Uno de ellos estaba relacionado con
matplotlib
y el backend que estaba usando. Debía estar relacionado con este commit. Por lo visto había que forzar a que usase un determinado backend constreamlit
pero al estar usando otras cosas comopandas
oseaborn
debía haber un conflicto al importar esas bibliotecas que también usanmatplotlib
y debían estar fijando el backend. Modifiqué los imports para intentar evitar eso y fijar el backend antes de que se importen otras cosas. - Otro problema era debido al soporte de
folium
dentro destreamlit
. Hasta ahora había que usar una “trampa”.
Ejecutando streamlit
usando MyBinder
Como he comentado, uno de los problemas que me encontré fue con matplotlib
. Parece que importando primero:
1 2 3 |
import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt |
Y después cosas como pandas
, xarray
o seaborn
, que pueden estar usando (e importando) matplotlib
, parece que resolvería el problema con el error relacionado con matplotlib
.
Después de resolver lo anterior, folium
daba un problema y no se mostraba correctamente en MyBinder. He tenido que modificar el código para usar un desarrollo último de un componente de streamlit
que permite usar folium
de forma más natural. El componente se llama streamlit-folium
y ha resuelto el problema que tenía. He tenido que modificar lo siguiente. Primero añadir el import del componente:
1 |
from streamlit_folium import folium_static |
Y luego sustituir esta línea:
1 |
mapa = create_map(lon, lat, tile=tile) |
Y esta otra:
1 |
st.markdown(mapa._repr_html_(), unsafe_allow_html=True) |
Por esta:
1 |
folium_static(create_map(lon, lat, tile=tile)) |
Puedes ver este commit y este otro.
Resuelto lo anterior hemos de intentar que se arranque streamlit
dentro de MyBinder. Para conseguir eso me ha hecho falta añadir dos ficheros. El primero llamará a streamlit
y lo arrancará como yo decida. Este fichero contiene el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from subprocess import Popen def load_jupyter_server_extension(nbapp): """serve the streamlit app""" Popen( [ "streamlit", "run", "app03.py", "--browser.serverAddress=0.0.0.0", "--server.enableCORS=False", "--runner.fixMatplotlib=True" ] ) |
El segundo fichero me permite ejecutar cosas después de que MyBinder haya montado lo necesario para correr el código, instalado las bibliotecas, etc. Este fichero se llama postBuild y contiene el siguiente código:
1 2 3 4 |
# streamlit launches at startup mv .binder/streamlit_call.py ${NB_PYTHON_PREFIX}/lib/python*/site-packages/ # enable streamlit extension jupyter serverextension enable --sys-prefix streamlit_call |
Lo último permite que streamlit
se ejecute gracias al uso de Jupyter-server-proxy. Jupyter-server-proxy permite ejecutar procesos externos arbitrarios y no solo limitarnos a ejecutar notebooks de Jupyter.
En esta parte final he adaptado parte de código que encontré en este repositorio de Chekos.
Resultado final
El resultado final es que ya funciona la aplicación en MyBinder y cualquier persona la puede probar sin necesidad de instalar nada en su propio equipo ni de descargar los datos que necesite la aplicación.
En el siguiente enlace puedes acceder a la aplicación.
Espero que le resulte útil a alguien.