[Python] Polars is less memory efficient than pandas

Discussão em 'Python' iniciado por Stack, Junho 24, 2025.

  1. Stack

    Stack Membro Participativo

    I'm testing the following script using pytest-memray:

    import pytest
    import pandas as pd
    import polars as pl


    @pytest.fixture
    def path() -> str:
    return "files/rows.csv"


    @pytest.fixture
    def path_xlsx() -> str:
    return "files/bankdataset.xlsx"


    def test_load_pandas(path: str):
    pd.read_csv(path)


    def test_load_polars(path: str):
    pl.scan_csv(path, low_memory=True).collect()


    def test_load_pandas_xlsx(path_xlsx: str):
    pd.read_excel(path_xlsx, sheet_name=None)


    def test_load_polars_xlsx(path_xlsx: str):
    pl.read_excel(path_xlsx, sheet_name=None)


    def test_load_pandas_partial(path: str):
    df = pd.read_csv(path, nrows=20)
    assert len(df) == 20


    def test_load_polars_partial(path: str):
    df = pl.scan_csv(path).head(n=20).collect()
    assert len(df) == 20


    def test_load_pandas_partial_xlsx(path_xlsx: str):
    df = pd.read_excel(path_xlsx, nrows=20)
    assert len(df) == 20


    def test_load_polars_partial_xlsx(path_xlsx: str):
    df = pl.read_excel(path_xlsx).head(n=20)
    assert len(df) == 20


    files/rows.csv is around 30k rows, and files/bankdataset.xlsx is 1 million rows.

    This outputs:

    ================================================================================================================ MEMRAY REPORT ================================================================================================================
    Allocation results for tests/test_load.py::test_load_polars_xlsx at the high watermark

    Total memory allocated: 473.5MiB
    Total allocations: 21
    Histogram of allocation sizes: |▁█▆ |
    Biggest allocating functions:
    - load_sheet_eager:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/fastexcel/__init__.py:424 -> 473.4MiB
    - _call_with_frames_removed:<frozen importlib._bootstrap>:488 -> 20.4KiB
    - read_excel:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/fastexcel/__init__.py:514 -> 13.9KiB
    - _compile_bytecode:<frozen importlib._bootstrap_external>:784 -> 9.6KiB
    - inner:/home/linuxbrew/.linuxbrew/opt/python@3.13/lib/python3.13/typing.py:429 -> 9.0KiB


    Allocation results for tests/test_load.py::test_load_polars_partial_xlsx at the high watermark

    Total memory allocated: 473.4MiB
    Total allocations: 7
    Histogram of allocation sizes: |█ |
    Biggest allocating functions:
    - load_sheet_eager:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/fastexcel/__init__.py:424 -> 473.4MiB
    - read_excel:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/fastexcel/__init__.py:514 -> 13.9KiB
    - _read_spreadsheet:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/polars/io/spreadsheet/functions.py:684 -> 536.0B


    Allocation results for tests/test_load.py::test_load_pandas_xlsx at the high watermark

    Total memory allocated: 426.2MiB
    Total allocations: 871
    Histogram of allocation sizes: | █▂ |
    Biggest allocating functions:
    - feed:/home/linuxbrew/.linuxbrew/opt/python@3.13/lib/python3.13/xml/etree/ElementTree.py:1291 -> 245.1MiB
    - parse_cell:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/openpyxl/worksheet/_reader.py:244 -> 63.0MiB
    - maybe_infer_to_datetimelike:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/pandas/core/dtypes/cast.py:1198 -> 39.3MiB
    - _rows_to_cols:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/pandas/io/parsers/python_parser.py:1066 -> 38.3MiB
    - _infer_types:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/pandas/io/parsers/base_parser.py:720 -> 15.3MiB


    Allocation results for tests/test_load.py::test_load_polars at the high watermark

    Total memory allocated: 172.5MiB
    Total allocations: 92
    Histogram of allocation sizes: |█ |
    Biggest allocating functions:
    - collect:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/polars/lazyframe/frame.py:2332 -> 96.0B


    Allocation results for tests/test_load.py::test_load_pandas at the high watermark

    Total memory allocated: 24.6MiB
    Total allocations: 25
    Histogram of allocation sizes: |█ ▁|
    Biggest allocating functions:
    - read:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/pandas/io/parsers/c_parser_wrapper.py:234 -> 18.6MiB
    - __init__:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/pandas/io/parsers/c_parser_wrapper.py:93 -> 6.0MiB
    - get_handle:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/pandas/io/common.py:873 -> 4.0KiB
    - _clean_options:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/pandas/io/parsers/readers.py:1688 -> 1.5KiB
    - read_csv:/home/monopoly/workspace/toys/sheetz/.venv/lib/python3.13/site-packages/pandas/io/parsers/readers.py:1009 -> 1.5KiB



    It appears that pandas beats polars in every aspect as far as memory efficiency. Is there something that I'm doing wrong? I'm trying to take advantage of LazyFrames with pl.scan_csv, but even that doesn't seem to help.

    Continue reading...

Compartilhe esta Página