Skip to content

Using both AsyncArray and Array from FSSpecStore #2909

Open
@ilan-gold

Description

@ilan-gold

Zarr version

v3.0.5

Numcodecs version

0.15.1

Python Version

3.13

Operating System

Mac

Installation

uv

Description

Hello! I'm trying to create an api around zarr async and I came across an edge case, maybe. I would like to be able to open the zarr store synchronously (potentially), but then use it asynchronously (hopefully). This seems to be specific to this store and not to zarr async i.e., the following works with a local file instead of an http server. Any advice? It would be great to write code that is synchronous at the top level, but then hooks into async at a lower level.

The weird part is that most of the anndata tests pass with this paradigm - the problem only arises in a script, or ipython sessions. This is likely just specific to remote stores, not some feature of how the program is run. Something to do with the event loop certainly? Any advice?

Steps to reproduce

ran in ipython/jupyter/script

from __future__ import annotations

import asyncio

import zarr.api
import zarr.api.asynchronous


async def main():
    g = await zarr.api.asynchronous.open_array(
        store="http://127.0.0.1:8080/242b59a3-7398-4f0d-89fc-73cbc886d1b9.zarr/X/data"
    )
    await g.getitem(Ellipsis)  # works
    g_sync = zarr.open_array(
        "http://127.0.0.1:8080/242b59a3-7398-4f0d-89fc-73cbc886d1b9.zarr/X/data"
    )
    await (await zarr.api.asynchronous.open_array(store=g_sync.store)).getitem(
        Ellipsis
    )  # fails
    await g_sync._async_array.getitem(()) # fails


if __name__ == "__main__":
    asyncio.run(main())
Traceback (most recent call last):
  File "/Users/ilangold/Projects/Theis/anndata/tester.py", line 23, in <module>
    asyncio.run(main())
    ~~~~~~~~~~~^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py", line 194, in run
    return runner.run(main)
           ~~~~~~~~~~^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/base_events.py", line 721, in run_until_complete
    return future.result()
           ~~~~~~~~~~~~~^^
  File "/Users/ilangold/Projects/Theis/anndata/tester.py", line 17, in main
    await (await zarr.api.asynchronous.open_array(store=g_sync.store)).getitem(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ilangold/Projects/Theis/anndata/venv/lib/python3.13/site-packages/zarr/api/asynchronous.py", line 1256, in open_array
    return await AsyncArray.open(store_path, zarr_format=zarr_format)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ilangold/Projects/Theis/anndata/venv/lib/python3.13/site-packages/zarr/core/array.py", line 896, in open
    metadata_dict = await get_array_metadata(store_path, zarr_format=zarr_format)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ilangold/Projects/Theis/anndata/venv/lib/python3.13/site-packages/zarr/core/array.py", line 177, in get_array_metadata
    zarr_json_bytes, zarray_bytes, zattrs_bytes = await gather(
                                                  ^^^^^^^^^^^^^
    ...<3 lines>...
    )
    ^
  File "/Users/ilangold/Projects/Theis/anndata/venv/lib/python3.13/site-packages/zarr/storage/_common.py", line 124, in get
    return await self.store.get(self.path, prototype=prototype, byte_range=byte_range)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ilangold/Projects/Theis/anndata/venv/lib/python3.13/site-packages/zarr/storage/_fsspec.py", line 230, in get
    value = prototype.buffer.from_bytes(await self.fs._cat_file(path))
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ilangold/Projects/Theis/anndata/venv/lib/python3.13/site-packages/fsspec/implementations/http.py", line 234, in _cat_file
    async with session.get(self.encode_url(url), **kw) as r:
               ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ilangold/Projects/Theis/anndata/venv/lib/python3.13/site-packages/aiohttp/client.py", line 1425, in __aenter__
    self._resp: _RetType = await self._coro
                           ^^^^^^^^^^^^^^^^
  File "/Users/ilangold/Projects/Theis/anndata/venv/lib/python3.13/site-packages/aiohttp/client.py", line 607, in _request
    with timer:
         ^^^^^
  File "/Users/ilangold/Projects/Theis/anndata/venv/lib/python3.13/site-packages/aiohttp/helpers.py", line 636, in __enter__
    raise RuntimeError("Timeout context manager should be used inside a task")

Additional output

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugPotential issues with the zarr-python library

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions