A Python wrapper for LittleFS filesystem designed for embedded systems with minimal RAM and flash requirements
—
The LittleFS class provides a Python-like filesystem interface with automatic mounting, familiar file I/O operations, and comprehensive error handling. This high-level API handles the complexity of the underlying LittleFS C library while providing intuitive Python semantics.
Main filesystem interface that provides Python-like file and directory operations with automatic configuration and error handling.
class LittleFS:
def __init__(self, context=None, mount=True, **kwargs) -> None:
"""
Initialize LittleFS filesystem.
Parameters:
- context: UserContext, storage backend (defaults to memory buffer)
- mount: bool, automatically mount after creation (default True)
- block_size: int, block size in bytes (default depends on context)
- block_count: int, number of blocks (default depends on context)
- name_max: int, maximum filename length (default 255)
- **kwargs: additional LFSConfig parameters
"""Core filesystem operations for formatting, mounting, and maintenance.
def format(self) -> int:
"""
Format the underlying buffer.
Returns:
int: 0 on success
Raises:
LittleFSError: If block_count is 0 or formatting fails
"""
def mount(self) -> int:
"""
Mount the underlying buffer.
Returns:
int: 0 on success
Raises:
LittleFSError: If mounting fails
"""
def unmount(self) -> int:
"""
Unmount the underlying buffer.
Returns:
int: 0 on success
"""
def fs_mkconsistent(self) -> int:
"""
Attempt to make the filesystem consistent and ready for writing.
Returns:
int: 0 on success
"""
def fs_grow(self, block_count: int) -> int:
"""
Grow filesystem to new size. WARNING: does not modify underlying context.
Parameters:
- block_count: int, new block count (must be >= current block_count)
Returns:
int: 0 on success
Raises:
ValueError: If block_count is smaller than current size
"""
def fs_stat(self) -> LFSFSStat:
"""
Get filesystem status information.
Returns:
LFSFSStat: Filesystem statistics
"""
def fs_gc(self):
"""
Perform garbage collection on the filesystem.
Returns:
int: 0 on success
"""High-level file I/O operations using Python's familiar file interface.
def open(self, fname: str, mode="r", buffering: int = -1, encoding: str = None,
errors: str = None, newline: str = None):
"""
Open a file with Python-like semantics.
Parameters:
- fname: str, path to file
- mode: str, file mode ('r', 'w', 'a', 'x', 'b', 't', '+')
- buffering: int, buffering policy (-1 for default, 0 for unbuffered in binary mode)
- encoding: str, text encoding (text mode only)
- errors: str, error handling (text mode only)
- newline: str, newline handling (text mode only)
Returns:
IO object (TextIOWrapper, BufferedReader, BufferedWriter, or FileHandle)
Raises:
FileNotFoundError: File not found
IsADirectoryError: Path is a directory
FileExistsError: File exists in exclusive create mode
ValueError: Invalid mode string
"""Directory creation, listing, and management with Python os module semantics.
def listdir(self, path=".") -> List[str]:
"""
List directory contents.
Parameters:
- path: str, directory path (default current directory)
Returns:
List[str]: List of filenames and directory names
"""
def mkdir(self, path: str) -> int:
"""
Create a directory.
Parameters:
- path: str, directory path to create
Returns:
int: 0 on success
Raises:
FileExistsError: Directory already exists
"""
def makedirs(self, name: str, exist_ok=False):
"""
Create directories recursively.
Parameters:
- name: str, directory path to create
- exist_ok: bool, don't raise error if final directory exists
Raises:
FileExistsError: Directory exists and exist_ok=False
"""
def scandir(self, path="."):
"""
Scan directory and yield LFSStat objects.
Parameters:
- path: str, directory path to scan
Yields:
LFSStat: File/directory status for each entry
"""
def rmdir(self, path: str) -> int:
"""
Remove a directory (alias for remove).
Parameters:
- path: str, directory path to remove
Returns:
int: 0 on success
"""
def removedirs(self, name):
"""
Remove directories recursively up the tree.
Parameters:
- name: str, directory path to start removal
"""File and directory manipulation operations.
def remove(self, path: str, recursive: bool = False) -> None:
"""
Remove a file or directory.
Parameters:
- path: str, path to remove
- recursive: bool, recursively remove directory contents
Raises:
FileNotFoundError: Path does not exist
"""
def rename(self, src: str, dst: str) -> int:
"""
Rename or move a file or directory.
Parameters:
- src: str, current path
- dst: str, new path
Returns:
int: 0 on success
"""
def stat(self, path: str) -> LFSStat:
"""
Get file or directory status.
Parameters:
- path: str, path to examine
Returns:
LFSStat: Status information (type, size, name)
"""
def unlink(self, path: str) -> int:
"""
Remove a file (alias for remove).
Parameters:
- path: str, file path to remove
Returns:
int: 0 on success
"""Extended attribute operations for storing metadata.
def getattr(self, path: str, typ: Union[str, bytes, int]) -> bytes:
"""
Get extended attribute value.
Parameters:
- path: str, file or directory path
- typ: str/bytes/int, attribute type (0-255)
Returns:
bytes: Attribute data
"""
def setattr(self, path: str, typ: Union[str, bytes, int], data: bytes) -> None:
"""
Set extended attribute value.
Parameters:
- path: str, file or directory path
- typ: str/bytes/int, attribute type (0-255)
- data: bytes, attribute data to store
"""
def removeattr(self, path: str, typ: Union[str, bytes, int]) -> None:
"""
Remove extended attribute.
Parameters:
- path: str, file or directory path
- typ: str/bytes/int, attribute type (0-255)
"""Directory tree traversal utilities.
def walk(self, top: str):
"""
Generate file names in directory tree by walking top-down.
Parameters:
- top: str, root directory to start walking
Yields:
Tuple[str, List[str], List[str]]: (root, dirs, files) for each directory
"""Filesystem information and context access.
@property
def block_count(self) -> int:
"""Total number of blocks in filesystem."""
@property
def used_block_count(self) -> int:
"""Number of blocks currently in use."""
@property
def context(self) -> UserContext:
"""User context (storage backend) of the filesystem."""from littlefs import LittleFS
# Create 1MB filesystem
fs = LittleFS(block_size=512, block_count=2048)
# Write configuration file
with fs.open('config.json', 'w') as f:
f.write('{"debug": true, "port": 8080}')
# Create directory structure
fs.makedirs('logs/app', exist_ok=True)
fs.makedirs('data/cache', exist_ok=True)
# Write log files
for i in range(3):
with fs.open(f'logs/app/log_{i}.txt', 'w') as f:
f.write(f'Log entry {i}\\n')
# List all files
for root, dirs, files in fs.walk('/'):
for file in files:
path = f"{root.rstrip('/')}/{file}"
stat_info = fs.stat(path)
print(f"{path}: {stat_info.size} bytes")# Set custom metadata
fs.setattr('config.json', 'version', b'1.2.0')
fs.setattr('config.json', 'created', b'2024-01-15')
# Read metadata
version = fs.getattr('config.json', 'version')
created = fs.getattr('config.json', 'created')
print(f"Version: {version.decode()}")
print(f"Created: {created.decode()}")# Check filesystem status
fs_stat = fs.fs_stat()
print(f"Block size: {fs_stat.block_size}")
print(f"Used blocks: {fs.used_block_count}/{fs.block_count}")
# Perform garbage collection if needed
if fs.used_block_count > fs.block_count * 0.8:
fs.fs_gc()
# Grow filesystem if needed
if fs.used_block_count > fs.block_count * 0.9:
fs.fs_grow(fs.block_count * 2)Install with Tessl CLI
npx tessl i tessl/pypi-littlefs-python