# Взаимодействие с Hub через Filesystem API

Помимо [HfApi](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_api#huggingface_hub.HfApi), библиотека `huggingface_hub` предоставляет [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem) — pythonic-интерфейс файловой системы, совместимый с [fsspec](https://filesystem-spec.readthedocs.io/en/latest/), для работы с Hugging Face Hub. [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem) построена на базе [HfApi](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_api#huggingface_hub.HfApi) и предлагает типичные файловые операции, такие как `cp`, `mv`, `ls`, `du`, `glob`, `get_file` и `put_file`.

> [!WARNING]
> [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem) обеспечивает совместимость с fsspec, что полезно для библиотек, требующих её (например, для прямого чтения датасетов и бакетов Hugging Face с помощью `pandas`). Однако этот слой совместимости вносит дополнительные накладные расходы. Для лучшей производительности и надёжности рекомендуется по возможности использовать методы [HfApi](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_api#huggingface_hub.HfApi).

## Использование

```python
>>> from huggingface_hub import hffs

>>> # List all files in a dataset directory
>>> hffs.ls("datasets/my-username/my-dataset-repo/data", detail=False)
['datasets/my-username/my-dataset-repo/data/train.csv', 'datasets/my-username/my-dataset-repo/data/test.csv']

>>> # List all files in a bucket directory
>>> hffs.ls("buckets/my-username/my-bucket/experiment-data", detail=False)
['bucket/my-username/my-bucket/data/train-0000.parquet', 'bucket/my-username/my-bucket/data/train-0001.parquet', ...]

>>> # List all ".csv" files in a dataset repository
>>> hffs.glob("datasets/my-username/my-dataset-repo/**/*.csv")
['datasets/my-username/my-dataset-repo/data/train.csv', 'datasets/my-username/my-dataset-repo/data/test.csv']

>>> # Read a remote file
>>> with hffs.open("datasets/my-username/my-dataset-repo/data/train.csv", "r") as f:
...     train_data = f.readlines()

>>> # Read the content of a remote file as a string
>>> train_data = hffs.read_text("datasets/my-username/my-dataset-repo/data/train.csv", revision="dev")

>>> # Write a remote file
>>> with hffs.open("datasets/my-username/my-dataset-repo/data/validation.csv", "w") as f:
...     f.write("text,label")
...     f.write("Fantastic movie!,good")
```

Необязательный аргумент `revision` можно передать для выполнения операции из конкретного коммита, например ветки, тега или хэша коммита. Обратите внимание, что `revision` несовместим с Buckets.

В отличие от встроенной в Python функции `open`, функция `open` из `fsspec` по умолчанию использует двоичный режим `"rb"`. Это означает, что для чтения и записи в текстовом режиме необходимо явно указать режимы `"r"` и `"w"` соответственно. Добавление данных в конец файла (режимы `"a"` и `"ab"`) пока не поддерживается.

## Список крупных репозиториев

Операции, перечисляющие файлы рекурсивно, такие как `find` и `glob`, требуют получения всего содержимого репозитория. Hub возвращает такие записи постранично, при этом запрос следующей страницы возможен только после получения предыдущей: для перечисления репозитория с 800 тыс. файлов требуется около 800 последовательных запросов, то есть примерно 30 минут.

Чтобы избежать этого, [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem) перечисляет содержимое крупных репозиториев по одному каталогу за раз, параллельно:

```python
>>> from huggingface_hub import hffs

>>> # Takes ~30s on a repository holding 800k files
>>> files = hffs.glob("datasets/allenai/objaverse/**/*.glb", maxdepth=3)
```

Количество одновременных запросов контролируется аргументом `max_workers` класса [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem). По умолчанию он равен 16; можно установить значение 1, чтобы отключить параллельное получение списков. Обратите внимание, что передача параметра `maxdepth` также значительно ускоряет получение списков, поскольку Hub в этом случае возвращает только фактически запрошенные записи.

## Держите списки актуальными

Каталоги перечисляются один раз, а их содержимое кэшируется, поэтому изменения, внесённые другим пользователем, не подхватываются автоматически. [HfFileSystem.invalidate_cache()](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem.invalidate_cache) сбрасывает кэшированные списки, либо для одного пути (и его родительских каталогов), либо для всех путей, если вызывается без аргументов:

```python
>>> hffs.ls("buckets/my-username/my-bucket/data", detail=False)  # listing is cached
>>> # ... another process uploads a file to the bucket ...
>>> hffs.invalidate_cache("buckets/my-username/my-bucket/data")
>>> hffs.ls("buckets/my-username/my-bucket/data", detail=False)  # listed again
['buckets/my-username/my-bucket/data/train.csv', 'buckets/my-username/my-bucket/data/new-file.csv']
```

Для бакетов `huggingface_hub` может сделать это за вас: Хаб транслирует изменения файлов в бакете по мере их появления, а [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem) удаляет из списков те записи, на которые повлияло изменение, сразу после его получения. Включите это с помощью `live_follow=True`:

```python
>>> from huggingface_hub import HfFileSystem
>>> hffs = HfFileSystem(live_follow=True)
>>> hffs.ls("buckets/my-username/my-bucket/data", detail=False)  # starts following that bucket
>>> # ... another process uploads a file to the bucket ...
>>> hffs.ls("buckets/my-username/my-bucket/data", detail=False)  # refreshed as changes arrive
['buckets/my-username/my-bucket/data/train.csv', 'buckets/my-username/my-bucket/data/new-file.csv']
```

Также его можно передать через fsspec, с помощью `fsspec.filesystem("hf", live_follow=True)` или через аргумент `storage_options` в библиотеках, которые его поддерживают (pandas, arrow, ...).

Несколько важных моментов:

- **Только корзины.** Репозитории моделей, наборов данных и пространств являются git-репозиториями, и Хаб не транслирует их изменения: передайте `refresh=True` в [HfFileSystem.ls()](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem.ls) (или используйте [HfApi.list_repo_tree()](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_api#huggingface_hub.HfApi.list_repo_tree)), чтобы увидеть новый коммит.
- **Обновляются только списки и их метаданные.** При чтении файла его содержимое всегда запрашивается с Hub, поэтому live following влияет только на то, что сообщают `ls`, `info`, `exists`, `glob`, ...
- Подписка начинается сразу после получения списка содержимого бакета, и для каждого отслеживаемого бакета поддерживается одно фоновое соединение, общее для всех экземпляров [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem). Именно поэтому данный параметр включается явно.

## Интеграции

Систему [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem) можно использовать с любой библиотекой, интегрирующей `fsspec`, при условии, что URL соответствует схеме:

```
hf://[<repo_type_prefix>]<repo_id>[@<revision>]/<path/in/repo>
```

`repo_type_prefix` — это `datasets/` для наборов данных, `spaces/` для Spaces, а для моделей префикс в URL не требуется.

Помимо репозиториев, [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem) также поддерживает Hugging Face Buckets, представляющие собой объектное хранилище, аналогичное S3 (подробнее см. [это руководство](./buckets)):

```
hf://buckets/<bucket_id>/<path/in/bucket>
```

Ниже перечислены некоторые интересные интеграции, в которых [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem) упрощает взаимодействие с Hub:

* Чтение/запись [Pandas](https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html#reading-writing-remote-files) DataFrame из/в репозиторий Hub:

  ```python
  >>> import pandas as pd

  >>> # Read a remote CSV file into a dataframe
  >>> df = pd.read_csv("hf://datasets/my-username/my-dataset-repo/train.csv")
  >>> df = pd.read_csv("hf://buckets/my-username/my-bucket/train.csv")

  >>> # Write a dataframe to a remote CSV file
  >>> df.to_csv("hf://datasets/my-username/my-dataset-repo/test.csv")
  >>> df.to_csv("hf://buckets/my-username/my-bucket/test.csv")
  ```

Этот же рабочий процесс можно использовать и для DataFrames в [Dask](https://docs.dask.org/en/stable/how-to/connect-to-remote-data.html) и [Polars](https://pola-rs.github.io/polars/py-polars/html/reference/io.html).

* Querying Файлы Hub (удалённые) с [DuckDB](https://duckdb.org/docs/guides/python/filesystems):

  ```python
  >>> from huggingface_hub import HfFileSystem
  >>> import duckdb

  >>> fs = HfFileSystem()
  >>> duckdb.register_filesystem(fs)
  >>> # Query a remote file and get the result back as a dataframe
  >>> fs_query_file = "hf://datasets/my-username/my-dataset-repo/data_dir/data.parquet"
  >>> df = duckdb.query(f"SELECT * FROM '{fs_query_file}' LIMIT 10").df()
  ```

* Использование Hub в качестве хранилища массивов с [Zarr](https://zarr.readthedocs.io/en/stable/tutorial.html#io-with-fsspec):

  ```python
  >>> import numpy as np
  >>> import zarr

  >>> embeddings = np.random.randn(50000, 1000).astype("float32")

  >>> # Write an array to a repo
  >>> root = zarr.open_group("hf://my-username/my-model-repo/array-store", mode="w")
  >>> foo = root.create_group("embeddings")
  >>> foobar = foo.zeros(name="experiment_0", shape=(50000, 1000), chunks=(10000, 1000), dtype="f4")
  >>> foobar[:] = embeddings

  >>> # Read an array from a repo
  >>> root = zarr.open_group("hf://my-username/my-model-repo/array-store", mode="r")
  >>> first_row = root["embeddings/experiment_0"][0]
  ```

## Аутентификация

Во многих случаях для взаимодействия с Hub необходимо войти в систему с учётной записью Hugging Face. Подробнее о методах аутентификации на Hub см. в разделе [Authentication](../quick-start#authentication) документации.

Также можно выполнить вход в систему программно, передав ваш `token` в качестве аргумента в [HfFileSystem](/docs/huggingface_hub/v2.4.0/ru/package_reference/hf_file_system#huggingface_hub.HfFileSystem):

```python
>>> from huggingface_hub import HfFileSystem
>>> hffs = HfFileSystem(token=token)
```

Если вы входите в систему таким образом, будьте осторожны, чтобы случайно не раскрыть токен при публикации исходного кода!

