fusepy (FUSE Python Bindings)
fusepy provides simple ctypes bindings for the FUSE (Filesystem in Userspace) library, allowing users to implement filesystems entirely in Python. The current version is 3.0.1, primarily focused on Python 3 compatibility and maintenance, with releases occurring infrequently as needed.
Warnings
- gotcha The PyPI package is named `fusepy`, but the module you import in your Python code is `fuse` (e.g., `from fuse import FUSE`). Importing from `fusepy` directly will fail.
- breaking Starting with version 3.0.0, fusepy officially dropped support for Python 2.x. It is now exclusively compatible with Python 3.
- gotcha fusepy is a binding to the FUSE system library, which must be installed on your operating system. Without it, `fusepy` cannot function.
- gotcha Failing to explicitly unmount a FUSE filesystem can leave a stale mount point, potentially requiring a system reboot or manual cleanup of the mount directory.
- gotcha FUSE operations can be concurrent, meaning multiple threads might call your `Operations` class methods simultaneously. Your filesystem implementation must handle thread safety if you modify shared state.
Install
-
pip install fusepy
Imports
- FUSE
from fusepy import FUSE
from fuse import FUSE
- Operations
from fusepy import Operations
from fuse import Operations
- FuseOSError
from fusepy import FuseOSError
from fuse import FuseOSError
Quickstart
import os
import errno
import sys
from stat import S_IFDIR, S_IFREG
import time
from fuse import FUSE, FuseOSError, Operations
# Define a simple in-memory filesystem
class HelloFS(Operations):
def __init__(self):
self.files = {
'/': {
'st_mode': (S_IFDIR | 0o755), 'st_nlink': 2, 'st_size': 0,
'st_ctime': time.time(), 'st_mtime': time.time(), 'st_atime': time.time()
},
'/hello.txt': {
'st_mode': (S_IFREG | 0o444), 'st_nlink': 1, 'st_size': 13,
'st_ctime': time.time(), 'st_mtime': time.time(), 'st_atime': time.time(),
'content': b"Hello FUSE!\n"
}
}
def getattr(self, path, fh=None):
if path not in self.files:
raise FuseOSError(errno.ENOENT)
# fusepy expects stat-like attributes directly
attrs = self.files[path]
return {
'st_mode': attrs['st_mode'],
'st_nlink': attrs['st_nlink'],
'st_size': attrs['st_size'],
'st_ctime': attrs['st_ctime'],
'st_mtime': attrs['st_mtime'],
'st_atime': attrs['st_atime'],
}
def readdir(self, path, fh):
dirents = ['.', '..']
if path == '/':
dirents.extend([f.lstrip('/') for f in self.files if f != '/'])
for r in dirents:
yield r
def open(self, path, flags):
if path not in self.files or 'content' not in self.files[path]:
raise FuseOSError(errno.ENOENT)
return 0 # FUSE expects a file handle, 0 is often used for in-memory FS
def read(self, path, size, offset, fh):
if path not in self.files or 'content' not in self.files[path]:
raise FuseOSError(errno.ENOENT)
content = self.files[path]['content']
return content[offset:offset + size]
if __name__ == '__main__':
# !!! IMPORTANT: You MUST have FUSE development libraries installed on your OS !!!
# For Debian/Ubuntu: sudo apt-get install libfuse-dev
# For macOS with Homebrew: brew install fuse-t
# The mount point can be specified as a command-line argument.
# Example usage: python your_script.py /tmp/myfuse
# To unmount: `fusermount -u /tmp/myfuse` (Linux) or `umount /tmp/myfuse` (macOS/BSD)
mount_point = sys.argv[1] if len(sys.argv) > 1 else '/tmp/myfuse_example'
if not os.path.exists(mount_point):
os.makedirs(mount_point)
print(f"Mounting filesystem at {mount_point}. Press Ctrl+C to unmount.")
print(f"To interact: ls {mount_point}, cat {mount_point}/hello.txt")
# The FUSE daemon starts here.
# foreground=True keeps the process in the foreground, useful for debugging.
# ro=True makes the filesystem read-only.
FUSE(HelloFS(), mount_point, foreground=True, ro=True)