mrkeyoor.com_
Tue 01 Sept 17:43 UTC
Dataevaluationupdated 26 Aug 2026

polars review

Polars is a dataframe query engine for analyzing structured data through Python, Rust, Node.js, R, or SQL. It helps developers replace row-by-row transformations with column expressions that the engine can optimize, run in parallel, and sometimes stream without holding the entire dataset in memory.

+86stars / 7d
Verdict

Our Polars sandbox installed 441 packages in 49 seconds, then both the build and tests failed because the linker could not find -lpython3.11, so source contributors need a prepared Python development toolchain. For users taking the packaged Python build, Polars is the first alternative we would test for a new analytical pipeline that can run on one machine. Adopt its expression model deliberately and keep data-contract tests around ingestion, timestamps, and Arrow or pandas interop.

We ran it

Lab card: what happened when we ran polarsScreenshot of polars (docs.pola.rs)
Install✓ · 49s441 packages
Build✗ · 459s
Tests✗ · 265sran, no count parsed
Repo3361 files~784,625 lines of source · 27.9 MB · 20 CI workflows

Answers from our run

Does polars build from source?

Dependencies installed in 49 seconds (441 packages), and the build failed. We cloned commit 586512b into a clean Debian container with 3 CPUs and no project-specific setup.

Do polars's tests pass?

The test command failed in our container, and its output did not report a pass or fail count.

Who should not use polars?

Teams that require drop-in pandas compatibility: Polars uses its own expression model, and migration means changing code rather than swapping an import.

What are the alternatives to polars?

pandas, DuckDB, DataFusion. Our Polars sandbox installed 441 packages in 49 seconds, then both the build and tests failed because the linker could not find `-lpython3.

Setup3/5Simple Python wheel, but our source build and tests failed at linking
Docs5/5Clear guides for Python, Rust, SQL, streaming, and special installs
Community5/5Daily repository activity and a large current issues and PR queue
Maturity4/5Established engine with frequent fixes and active API deprecations

Discussed on

  1. hn650GB of Data (Delta Lake on S3). Polars vs. DuckDB vs. Daft vs. Spark263 points
  2. hnPolars Cloud: The Distributed Cloud Architecture to Run Polars Anywhere261 points
  3. hnWhy Polars rewrote its Arrow string data type226 points
  4. hnPython Polars Cheatsheet (based on our O'Reilly book)198 points
  5. hnA bird's eye view of Polars197 points

Who it’s for

Python data teams prepared to rewrite pandas-style pipelines around expressions and lazy queries.
Engineers processing Parquet, CSV, Arrow, Delta, or Iceberg data on one capable machine.
Rust developers who want a native dataframe engine with Python and other language bindings.
Teams that will test schemas, timestamps, nulls, and query results at system boundaries.

Who it’s NOT for

Teams that require drop-in pandas compatibility: Polars uses its own expression model, and migration means changing code rather than swapping an import.
Operators who need an open-source distributed cluster scheduler: the README directs horizontal scaling to Polars Cloud, while the core engine focuses on one machine.
Contributors expecting a stock Debian source build to work after fetching Rust dependencies: our build and test commands both stopped when the linker could not find -lpython3.11.
Users on old CPUs, more than roughly 4.2 billion rows, or x86-64 Python under Rosetta who cannot choose a special install path: the README calls out each case.
GPU teams without supported NVIDIA hardware: the README describes GPU acceleration as optional and NVIDIA-specific.

Setup reality

In our sandbox, dependency installation succeeded in 49 seconds and installed 441 packages. The build then failed after 459 seconds with exit 101, and the tests failed after 265 seconds with exit 101. Both log tails ended at the same linker error: rust-lld could not find -lpython3.11 while compiling polars-dylib.

The ordinary Python route in the README is pip install polars, with no credentials or hosted service required for local dataframe work. Source builds are different: the README requires a current Rust compiler and maturin, then offers several build profiles inside py-polars. Cloud storage, GPU execution, plugins, and Polars Cloud add their own configuration outside that basic path.

Our checkout at commit 586512b contained 3,361 files and about 784,625 source lines, so contributors are entering a large mixed Rust and Python workspace. The README also calls out separate packages for old CPUs, indexes beyond roughly 4.2 billion rows, and Rosetta on Apple Silicon. It does not mention the missing Python linker library shown by our fresh Debian run.

Polars turns dataframe work into optimized queries

Polars presents familiar dataframe operations, but its engine is built around column expressions and query plans. A user can scan a file, filter rows, group by a column, aggregate values, sort the result, and collect it through Python. Rust does the execution work underneath, with interfaces also documented for Node.js, R, and SQL. Apache Arrow provides the columnar interchange layer.

The checkout we ran at commit 586512b was substantial: 3,361 files, about 784,625 source lines, and 27.9 MB on disk. That scale makes sense once you see the scope. This repository contains the Rust engine, Python bindings, streaming machinery, I/O integrations, SQL support, and plugin surfaces. It is a serious data system, not a small Python package that happens to call native code.

Lazy execution is the reason to change APIs

The strongest case for Polars is its lazy API. Instead of executing each transformation immediately, a lazy scan builds a plan that can discard unused columns, move filters nearer the source, and run independent work in parallel. The expression syntax also makes relationships between columns explicit. That is useful in maintained pipelines where readers need to see the intended computation, not a trail of mutated intermediate frames.

The README says streaming can process queries, or parts of them, when the dataset is larger than memory, and gives 250 GB on a laptop as an example of what may be possible. That figure is illustrative, since success depends on the operations and file layout. Streaming should be tested against the actual query. A sort, join, or other blocking operation may have a different memory profile from a simple filtered scan.

Migration is therefore a rewrite, not an import alias. Code built around pandas indexes, per-row functions, loose object columns, or repeated mutation needs a different shape. That cost can be worthwhile for a production transformation that runs often. It is harder to justify for a short notebook whose dependencies already expect pandas objects. Polars can exchange Arrow data and convert to or from pandas, but every boundary still deserves type and null checks.

What happened when we ran it

In our sandbox, installation completed in 49 seconds and brought in 441 packages. The repository was tested at commit 586512b inside an unprivileged Debian container with 3 CPUs and 12 GB of RAM. There was no Dockerfile in the 3,361-file checkout and no top-level tests directory, although the repository contains 20 CI workflow files. Those layout signals do not tell us whether the code works, so we relied on the command results.

The build did not complete. It ran for 459 seconds, exited with code 101, and stopped while compiling polars-dylib. The final linker message was specific: rust-lld could not find -lpython3.11. The log does not establish anything beyond that missing library, so we will not turn it into a broader diagnosis. It does show that the dependency install alone did not prepare this fresh Debian environment for the repository build.

Tests reached the same boundary. They ran for 265 seconds, exited with code 101, and ended with the same -lpython3.11 linker error while polars-dylib was compiling. No test count was produced in the supplied summary, and a compile failure is not evidence that assertions failed. The honest result is narrower: our run could not reach the suite because the required library was unavailable to the linker.

The Python wheel is easier than the source workspace

For an application developer, the README starts with one command: pip install polars. Prebuilt Python packages avoid the source-build path we hit, and local dataframe work needs no account, API token, database, or server. That makes a trial easy. Load a representative Parquet or CSV file, express one real transformation, and compare the result with the current pipeline before discussing a migration.

Contributors face more machinery. The documented source path requires a current Rust compiler, maturin, and work inside py-polars; it then offers 6 build profiles with different compile-time and runtime tradeoffs. Hardware also matters. The README calls for a separate choice on CPUs without AVX2, for more than roughly 4.2 billion rows, and when x86-64 Python runs under Rosetta on Apple Silicon.

Python Polars 1.44.0 shows a fast-moving API

Python Polars 1.44.0 was released on August 24, 2026, and the repository was pushed again on August 25. GitHub reported 39,489 stars and 2,859 open issues and pull requests when we fetched it. Recent activity included a documentation report about compressed CSV behavior alongside fixes and feature work. This is an active project with a busy combined queue, not 2,859 confirmed bugs.

The 1.44.0 notes mix optimizer work, SQL and Iceberg additions, deprecations, and fixes for incorrect loads, null handling, overflow, Arrow imports, and data corruption in a nested Arrow case. Frequent fixes are reassuring, but the subjects also show where mistakes become expensive. Pin releases, read upgrade notes, and run contract tests for schemas, decimals, dates, categoricals, nulls, and round trips through other dataframe libraries.

Choose Polars for analytical work on one machine

Polars is a strong default candidate when a team owns its transformation code, works with columnar files, and can learn the expression API. Lazy planning gives the engine room to remove work before execution, while streaming can extend the size of jobs that fit one machine. The language bindings also let a Rust-centered engine sit inside a Python-facing data stack.

Our 12 GB sandbox did not prove the engine's runtime behavior because compilation stopped before tests, and that limits what we can claim. It did prove that the 441-package setup was insufficient for this source checkout. Evaluate the packaged wheel first unless source development is the goal. Choose pandas when compatibility dominates, DuckDB when SQL is the natural interface, and DataFusion when the task is building a query engine rather than using a dataframe library.

Alternatives

ProjectWhat it isPick it when
pandas gh↗Python's standard labeled-dataframe library with broad third-party support.pick this instead when compatibility with existing notebooks and Python data libraries matters more than lazy execution.
DuckDB gh↗An embedded analytical database that queries files and dataframes with SQL.pick this instead when SQL, joins, and database semantics are the center of the workload.
DataFusion gh↗A Rust and Apache Arrow query engine built for embedding and extension.pick this instead when you are building a custom query system rather than choosing an end-user dataframe API.

What people are saying

  1. [github-trending] pola-rs/polars
  2. [hackernews] Python Polars Cheatsheet (based on our O'Reilly book)

Sources

  1. Polars repository and README
  2. Polars installation guide
  3. Polars coming from pandas guide
  4. Python Polars 1.44.0 release notes
  5. Compressed CSV documentation issue 28978

More data reviews

turso · TrackersListCollection · dash · getcontact-cli · awesome-zhuiju-free · iggy · the whole board →