fsspec / fsspec/filesystem_spec

Inconsistent behavior with fsspec.open with mode='r' vs. mode='rb'

Open
#579 13 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.4k
Forks
490
Avg merge
2d 3h
Merged PRs (30d)
38

Description

It's unclear to me how to use fsspec.open as a contextmanager. The behavior of this function seems inconsistent. The inconsistency is somehow related to the mode argument. I will try to illustrate this with an example.

Create a test file

Bypass fsspec completely

fname = 'test.txt'
with open(fname, mode='w') as f:
    f.write('hello')
Open the file with a FileSystem instance

When I open the file via an instantiated FileSystem instance, everything works as I expect

fs = fsspec.implementations.local.LocalFileSystem()
with fs.open(fname, mode='r') as fp:
    print(type(fp))
# -> <class '_io.TextIOWrapper'>
with fs.open(fname, mode='rb') as fp:
    print(type(fp))
# -> <class '_io.BufferedReader'>

The objects yielded to the context manager look like standard open file objects and can be used as such throughout python.

Open the file via fsspec.open
with fsspec.open(fname, mode='r') as fp:
    print(type(fp))
# -> <class '_io.TextIOWrapper'>
with fsspec.open(fname, mode='rb') as fp:
    print(type(fp))
# -> <class 'fsspec.implementations.local.LocalFileOpener'>

With mode='r', the fsspec.open yields object is the same type of object as fs.open. But with mode='rb', we get a LocalFileOpener. ⚠️ this is the key problem. In order to get a BufferedReader, we need an additional context manager!

with fsspec.open(fname) as fp:
    with fp as fp2:
        print(type(fp2))
# -> <class '_io.BufferedReader'>

I can't figure out what this LocalFileOpener object is. It's not documented in the API docs. Most importantly for my purposes, xarray can't figure out what to do with it if I pass it to open_dataset. In contrast, it handles an _io.BufferedReader object fine.

Proposed resolution

I would propose to remove the inconsistency and have with fsspec.open(fname, mode='rb') yield an _io.BufferedReader object. However, I recognize this could be a breaking change for some applications that rely on the LocalFileOpener.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue does not name a source file or test path. Reproduce the two fsspec.open examples, then trace how mode='r' and mode='rb' enter their context managers and compare that behavior with FileSystem.open. Done means the intended context-manager behavior is consistent and remains usable by xarray, with regression coverage for both modes.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.