<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Python el josiete.com</title><link>https://www.josiete.com/tags/python/</link><description>Contenido reciente en Python el josiete.com</description><generator>Hugo</generator><language>es-es</language><lastBuildDate>Thu, 24 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.josiete.com/tags/python/index.xml" rel="self" type="application/rss+xml"/><item><title>Polars: Python acelera sus DataFrames con Rust y varios hilos</title><link>https://www.josiete.com/posts/polars-python/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://www.josiete.com/posts/polars-python/</guid><description>&lt;p&gt;&lt;img src="https://www.josiete.com/images/polars-python.webp" alt="Ilustración del logo de Polars rodeado de columnas de datos y líneas de procesamiento paralelo"&gt;&lt;/p&gt;&#10;&lt;p&gt;Python sigue siendo uno de los lenguajes más cómodos para explorar y transformar datos. Sin embargo, la comodidad de un DataFrame no siempre se traduce en velocidad: cuando crecen las columnas y las filas, el coste de memoria y de CPU se vuelve muy visible. &lt;a href="https://pola.rs/"&gt;Polars&lt;/a&gt; aborda ese problema con una librería de DataFrames escrita en Rust y con una API disponible desde Python.&lt;/p&gt;&#10;&lt;h2 id="qué-es-polars"&gt;¿Qué es Polars?&lt;/h2&gt;&#10;&lt;p&gt;Polars es un motor de consultas analíticas y una librería de DataFrames para trabajar con datos tabulares. Su núcleo está escrito en Rust, utiliza un modelo de memoria compatible con Apache Arrow y combina ejecución vectorizada, optimización de consultas y procesamiento por columnas.&lt;/p&gt;&#10;&lt;p&gt;La API ofrece dos estilos. El modo eager ejecuta cada operación al momento, algo útil para exploraciones interactivas. El modo lazy construye un plan de consulta: Polars puede reordenar operaciones, eliminar columnas que no hacen falta y aplicar filtros tan pronto como sea posible antes de ejecutar el resultado.&lt;/p&gt;&#10;&lt;p&gt;No es una sustitución universal de una base de datos o de un sistema distribuido. Su punto fuerte es exprimir una máquina —portátil o servidor— y trabajar con CSV, Parquet, JSON y otras fuentes sin obligar al usuario a administrar un clúster.&lt;/p&gt;&#10;&lt;h2 id="el-paralelismo-más-de-un-hilo-sin-escribir-código-de-concurrencia"&gt;El paralelismo: más de un hilo sin escribir código de concurrencia&lt;/h2&gt;&#10;&lt;p&gt;Una diferencia importante frente a muchos flujos tradicionales de Python es que Polars no delega todo el trabajo pesado en el hilo principal del intérprete. Las operaciones del motor están implementadas en Rust y su planificador utiliza un &lt;em&gt;thread pool&lt;/em&gt; para repartir tareas entre los núcleos disponibles. El motor es vectorizado, columnar y multihilo; por eso un filtro, una agregación o un &lt;code&gt;join&lt;/code&gt; puede aprovechar varios cores automáticamente.&lt;/p&gt;&#10;&lt;p&gt;En la práctica, esto significa que el usuario escribe expresiones normales de Polars y el motor decide cómo paralelizarlas. No hace falta crear un &lt;code&gt;ThreadPoolExecutor&lt;/code&gt;, serializar cada partición ni coordinar manualmente los resultados. La API de Python actúa como una interfaz; el cálculo intensivo ocurre en el núcleo nativo.&lt;/p&gt;&#10;&lt;p&gt;Se puede consultar el tamaño del grupo de hilos con &lt;code&gt;pl.thread_pool_size()&lt;/code&gt; en versiones actuales. Polars lo configura automáticamente de forma razonable, pero en un entorno compartido —por ejemplo, dentro de un worker que ya limita la CPU— puede fijarse &lt;code&gt;POLARS_MAX_THREADS&lt;/code&gt; antes de importar la librería:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;POLARS_MAX_THREADS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; python analizar_ventas.py&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Conviene no confundir este paralelismo con la ejecución distribuida: varios hilos aprovechan los núcleos de una sola máquina. Para datos que no caben en memoria, el motor lazy también puede ejecutar en streaming cuando el plan lo permite; para escalar horizontalmente existe una capa distribuida separada.&lt;/p&gt;&#10;&lt;h2 id="la-empresa-detrás-del-proyecto"&gt;La empresa detrás del proyecto&lt;/h2&gt;&#10;&lt;p&gt;Polars nació en 2020 como un proyecto personal de &lt;a href="https://pola.rs/about-us/"&gt;Ritchie Vink&lt;/a&gt;, inicialmente para aprender sobre motores de consultas, Apache Arrow y Rust. El 3 de agosto de 2023, Vink y &lt;a href="https://pola.rs/posts/company-announcement/"&gt;Chiel Peters&lt;/a&gt; anunciaron la creación de Polars Inc., una empresa con sede en Ámsterdam orientada a aportar ingeniería y estabilidad a largo plazo al ecosistema.&lt;/p&gt;&#10;&lt;p&gt;La empresa no sustituyó al proyecto comunitario: Polars continúa siendo software libre bajo licencia MIT. Su objetivo es financiar el desarrollo del motor, mejorar conectores y ofrecer productos para ejecutar consultas a mayor escala, incluido Polars Cloud. Es una separación interesante: una compañía puede construir servicios comerciales alrededor del proyecto mientras el núcleo abierto sigue disponible para cualquiera.&lt;/p&gt;&#10;&lt;h2 id="un-ejemplo-en-python"&gt;Un ejemplo en Python&lt;/h2&gt;&#10;&lt;p&gt;Instalamos la librería con &lt;code&gt;pip&lt;/code&gt; y construimos una pequeña transformación. &lt;code&gt;scan_csv&lt;/code&gt; devuelve un &lt;code&gt;LazyFrame&lt;/code&gt;, por lo que las operaciones se planifican y &lt;code&gt;collect()&lt;/code&gt; ejecuta el plan optimizado.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pip install polars&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; polars &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; pl&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ventas &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pl&lt;span style="color:#f92672"&gt;.&lt;/span&gt;scan_csv(&lt;span style="color:#e6db74"&gt;&amp;#34;ventas.csv&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;resultado &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ventas&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;filter(pl&lt;span style="color:#f92672"&gt;.&lt;/span&gt;col(&lt;span style="color:#e6db74"&gt;&amp;#34;estado&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;pagado&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;with_columns(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (pl&lt;span style="color:#f92672"&gt;.&lt;/span&gt;col(&lt;span style="color:#e6db74"&gt;&amp;#34;unidades&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; pl&lt;span style="color:#f92672"&gt;.&lt;/span&gt;col(&lt;span style="color:#e6db74"&gt;&amp;#34;precio&amp;#34;&lt;/span&gt;))&lt;span style="color:#f92672"&gt;.&lt;/span&gt;alias(&lt;span style="color:#e6db74"&gt;&amp;#34;importe&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;group_by(&lt;span style="color:#e6db74"&gt;&amp;#34;categoria&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;agg(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pl&lt;span style="color:#f92672"&gt;.&lt;/span&gt;col(&lt;span style="color:#e6db74"&gt;&amp;#34;importe&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sum()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;alias(&lt;span style="color:#e6db74"&gt;&amp;#34;facturacion&amp;#34;&lt;/span&gt;),&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pl&lt;span style="color:#f92672"&gt;.&lt;/span&gt;col(&lt;span style="color:#e6db74"&gt;&amp;#34;unidades&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sum()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;alias(&lt;span style="color:#e6db74"&gt;&amp;#34;unidades&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;sort(&lt;span style="color:#e6db74"&gt;&amp;#34;facturacion&amp;#34;&lt;/span&gt;, descending&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;collect()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(resultado)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El código expresa qué queremos obtener y deja que Polars decida cómo recorrer las columnas y repartir el trabajo. En un fichero grande, el modo lazy puede evitar leer columnas innecesarias y empujar el filtro hacia la lectura. Si el origen ya es Parquet, &lt;code&gt;pl.scan_parquet(&amp;quot;datos/*.parquet&amp;quot;)&lt;/code&gt; permite mantener el mismo patrón.&lt;/p&gt;&#10;&lt;h2 id="cuándo-elegirlo"&gt;¿Cuándo elegirlo?&lt;/h2&gt;&#10;&lt;p&gt;Polars encaja especialmente bien en pipelines de transformación, análisis exploratorio con volúmenes grandes, preparación de datos para modelos y servicios que necesitan respuestas rápidas sin levantar un sistema distribuido. Si el proyecto depende de un ecosistema concreto de pandas, la migración requiere revisar algunas operaciones y tipos; aun así, ambas librerías pueden convivir y Polars permite convertir a pandas cuando sea necesario.&lt;/p&gt;&#10;&lt;p&gt;La idea central es sencilla: Python conserva una interfaz expresiva, mientras Rust se ocupa del trabajo intensivo, la memoria y el paralelismo. Esa combinación convierte a Polars en una opción muy atractiva cuando un DataFrame deja de ser pequeño, pero todavía queremos que el análisis viva cerca de nuestro código.&lt;/p&gt;&#10;</description></item></channel></rss>