Python bindings for FUSE (Filesystem in USErspace) enabling custom userspace filesystems
npx @tessl/cli install tessl/pypi-fuse-python@1.0.0Python bindings for FUSE (Filesystem in USErspace) that enable developers to create custom filesystems running in user space. The library provides a comprehensive interface to libfuse functionality, allowing implementation of virtual filesystems with full POSIX filesystem operation support including file I/O, directory operations, metadata handling, and advanced features like extended attributes and file locking.
pip install fuse-pythonimport fuse
from fuse import FuseEssential exception handling:
from fuse import FuseErrorSet API version (recommended):
fuse.fuse_python_api = (0, 2)Advanced imports (for low-level operations):
from fuse import FuseGetContext, FuseInvalidate, FuseNotifyPoll
from fuse import APIVersion, feature_needs, feature_assertimport fuse
from fuse import Fuse
import stat
import errno
# Set API version
fuse.fuse_python_api = (0, 2)
class HelloFS(Fuse):
"""Simple filesystem that shows a single file."""
def getattr(self, path):
"""Get file/directory attributes."""
st = fuse.Stat()
if path == '/':
st.st_mode = stat.S_IFDIR | 0o755
st.st_nlink = 2
elif path == '/hello':
st.st_mode = stat.S_IFREG | 0o444
st.st_nlink = 1
st.st_size = 13
else:
return -errno.ENOENT
return st
def readdir(self, path, offset):
"""Read directory contents."""
for r in '.', '..', 'hello':
yield fuse.Direntry(r)
def read(self, path, size, offset):
"""Read file content."""
if path != '/hello':
return -errno.ENOENT
content = b'Hello World!\n'
return content[offset:offset+size]
# Create and run filesystem
fs = HelloFS(version="HelloFS 1.0")
fs.parse()
fs.main()fuse-python uses a class-based architecture where filesystem implementations inherit from the Fuse base class:
Stat, StatVfs, Direntry, etc.)FuseArgs and FuseOptParsefuseparts._fuse module provides the FUSE library interfaceEssential filesystem operations that must be implemented for basic functionality, including file and directory attribute retrieval, directory listing, and file content operations.
def getattr(self, path):
"""Get file/directory attributes. Returns Stat object or negative errno."""
def readdir(self, path, offset):
"""Read directory contents. Yields Direntry objects."""
def read(self, path, size, offset):
"""Read file content. Returns bytes or negative errno."""
def write(self, path, buf, offset):
"""Write file content. Returns bytes written or negative errno."""Operations for creating, removing, and modifying files and directories, including symbolic links and permission changes.
def mknod(self, path, mode, dev):
"""Create a file node. Returns 0 on success or negative errno."""
def mkdir(self, path, mode):
"""Create directory. Returns 0 on success or negative errno."""
def unlink(self, path):
"""Remove file. Returns 0 on success or negative errno."""
def rmdir(self, path):
"""Remove directory. Returns 0 on success or negative errno."""FUSE data structures for representing file attributes, directory entries, and other filesystem metadata.
class Stat:
"""File/directory attributes."""
st_mode: int
st_ino: int
st_size: int
st_atime: int
st_mtime: int
st_ctime: int
class Direntry:
"""Directory entry."""
name: str
type: int
ino: int
offset: intIntegrated command line argument processing and FUSE option management for filesystem mounting and configuration.
class FuseArgs:
"""FUSE command line arguments."""
mountpoint: str
modifiers: dict
def parse(self, *args, **kwargs):
"""Parse command line arguments."""
def main(self):
"""Enter filesystem service loop."""Advanced FUSE features including extended attributes, file locking, access control, and filesystem statistics.
def getxattr(self, path, name, size):
"""Get extended attribute value."""
def setxattr(self, path, name, val, flags):
"""Set extended attribute value."""
def access(self, path, mode):
"""Check file access permissions."""
def lock(self, path, fip, cmd, lock):
"""File locking operations."""All filesystem operations should return appropriate errno values for errors:
-errno.ENOENT) for errorsOSError or IOError exceptionserrno moduleThe library provides a specialized exception for FUSE-specific errors:
try:
# FUSE operation that might fail
result = fuse.feature_assert('has_init')
except fuse.FuseError as e:
print(f"FUSE error: {e}")The library automatically converts Python exceptions to appropriate errno values:
def read(self, path, size, offset):
try:
return self.files[path][offset:offset+size]
except KeyError:
# Automatically converted to -errno.ENOENT
raise OSError(errno.ENOENT, "File not found")
except Exception as e:
# Generic errors become EIO
raise OSError(errno.EIO, str(e))fuse-python supports multiple API versions for backward compatibility:
(0, 2) - Recommended for new code(0, 1) - For compatibility with older codeSet the API version before creating filesystem instances:
fuse.fuse_python_api = (0, 2)Or use environment variable:
export FUSE_PYTHON_API=0.2# Check current API version
api_version = fuse.get_fuse_python_api()
print(f"Using API version: {api_version}")
# Check if using legacy 0.1 compatibility
if fuse.get_compat_0_1():
print("Running in 0.1 compatibility mode")
# Get underlying FUSE library version
fuse_version = fuse.APIVersion()
print(f"FUSE library version: {fuse_version}")
# Check feature availability and requirements
try:
# Check if specific features are available
version_needed = fuse.feature_needs('has_init', 'has_destroy')
print(f"Features require API version: {version_needed}")
# Assert that features are available (raises FuseError if not)
fuse.feature_assert('has_init', 'has_destroy')
print("All required features are available")
except fuse.FuseError as e:
print(f"Feature check failed: {e}")Filesystems can be multithreaded by setting the multithreaded attribute:
class MyFS(Fuse):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.multithreaded = TrueThread safety depends on the filesystem implementation.