fusepy (FUSE Python Bindings)

3.0.1 · active · verified Wed Apr 15

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

Install

Imports

Quickstart

This quickstart implements a basic, read-only filesystem with a single file '/hello.txt'. To run it, save the code and execute `python your_script.py /tmp/myfuse`. You'll need FUSE development libraries installed on your host system (e.g., `libfuse-dev` on Linux or `fuse-t` via Homebrew on macOS). Access the mounted filesystem with `ls /tmp/myfuse` or `cat /tmp/myfuse/hello.txt`. Press Ctrl+C to unmount, or use `fusermount -u /tmp/myfuse` (Linux) / `umount /tmp/myfuse` (macOS).

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)

view raw JSON →