0
# File System
1
2
Access and manipulate the Emscripten virtual file system with support for mounting host directories and browser file systems.
3
4
## File System API
5
6
### FS
7
8
Complete Emscripten file system interface for file and directory operations.
9
10
```javascript { .api }
11
const FS: {
12
// File operations
13
readFile(path: string, options?: { encoding?: string }): string | Uint8Array;
14
writeFile(path: string, data: string | ArrayBufferView, options?: { encoding?: string }): void;
15
unlink(path: string): void;
16
rename(oldPath: string, newPath: string): void;
17
18
// Directory operations
19
mkdir(path: string, mode?: number): void;
20
rmdir(path: string): void;
21
readdir(path: string): string[];
22
23
// File information
24
stat(path: string): FSStats;
25
lstat(path: string): FSStats;
26
exists(path: string): boolean;
27
28
// File system mounting
29
mount(type: any, options: any, mountpoint: string): void;
30
unmount(mountpoint: string): void;
31
32
// Additional utilities
33
mkdirTree(path: string): void;
34
lookupPath(path: string, options?: any): { path: string; node: any };
35
isFile(mode: number): boolean;
36
isDir(mode: number): boolean;
37
isLink(mode: number): boolean;
38
isChrdev(mode: number): boolean;
39
isBlkdev(mode: number): boolean;
40
isFIFO(mode: number): boolean;
41
isSocket(mode: number): boolean;
42
43
// File systems
44
filesystems: {
45
MEMFS: any;
46
IDBFS: any;
47
NODEFS: any;
48
PROXYFS: any;
49
WORKERFS: any;
50
NATIVEFS_ASYNC: any;
51
};
52
};
53
```
54
55
### PATH
56
57
Path manipulation utilities similar to Node.js path module.
58
59
```javascript { .api }
60
const PATH: {
61
dirname(path: string): string;
62
basename(path: string, ext?: string): string;
63
extname(path: string): string;
64
join(...paths: string[]): string;
65
resolve(...paths: string[]): string;
66
normalize(path: string): string;
67
isAbsolute(path: string): boolean;
68
relative(from: string, to: string): string;
69
sep: string;
70
delimiter: string;
71
};
72
```
73
74
## Mounting External File Systems
75
76
### mountNodeFS
77
78
Mount a host directory into the virtual file system (Node.js only).
79
80
```javascript { .api }
81
function mountNodeFS(emscriptenPath: string, hostPath: string): void;
82
```
83
84
**Parameters:**
85
- `emscriptenPath` - Virtual file system mount point (must be absolute)
86
- `hostPath` - Host directory path to mount
87
88
### mountNativeFS
89
90
Mount a browser FileSystemDirectoryHandle into the virtual file system.
91
92
```javascript { .api }
93
function mountNativeFS(
94
path: string,
95
fileSystemHandle: FileSystemDirectoryHandle
96
): Promise<NativeFS>;
97
```
98
99
**Parameters:**
100
- `path` - Virtual file system mount point (must be absolute)
101
- `fileSystemHandle` - Browser FileSystemDirectoryHandle
102
103
**Returns:** Promise resolving to NativeFS object with sync capabilities
104
105
## Usage Examples
106
107
### Basic File Operations
108
109
```javascript
110
// Create directories
111
pyodide.FS.mkdir("/workspace");
112
pyodide.FS.mkdir("/data");
113
114
// Write files
115
pyodide.FS.writeFile("/workspace/config.py", `
116
DEBUG = True
117
DATABASE_URL = "sqlite:///app.db"
118
SECRET_KEY = "development-key"
119
`);
120
121
pyodide.FS.writeFile("/data/sample.txt", "Hello from Pyodide file system!");
122
123
// Read files
124
const configContent = pyodide.FS.readFile("/workspace/config.py", { encoding: "utf8" });
125
console.log("Config file:", configContent);
126
127
const binaryData = pyodide.FS.readFile("/data/sample.txt"); // Returns Uint8Array
128
const textData = pyodide.FS.readFile("/data/sample.txt", { encoding: "utf8" });
129
console.log("Text data:", textData);
130
```
131
132
### Directory Operations
133
134
```javascript
135
// Create nested directories
136
pyodide.FS.mkdirTree("/project/src/utils");
137
138
// List directory contents
139
const files = pyodide.FS.readdir("/workspace");
140
console.log("Workspace files:", files);
141
142
// Check if path exists
143
if (pyodide.FS.exists("/workspace/config.py")) {
144
console.log("Config file exists");
145
}
146
147
// Get file information
148
const stats = pyodide.FS.stat("/workspace/config.py");
149
console.log("File size:", stats.size);
150
console.log("Modified:", new Date(stats.mtime));
151
console.log("Is file:", pyodide.FS.isFile(stats.mode));
152
console.log("Is directory:", pyodide.FS.isDir(stats.mode));
153
```
154
155
### Path Manipulation
156
157
```javascript
158
// Join paths
159
const configPath = pyodide.PATH.join("/workspace", "config.py");
160
console.log("Config path:", configPath); // /workspace/config.py
161
162
// Get directory and filename
163
console.log("Directory:", pyodide.PATH.dirname(configPath)); // /workspace
164
console.log("Filename:", pyodide.PATH.basename(configPath)); // config.py
165
console.log("Extension:", pyodide.PATH.extname(configPath)); // .py
166
167
// Normalize paths
168
const messyPath = "/workspace/../workspace/./config.py";
169
console.log("Normalized:", pyodide.PATH.normalize(messyPath)); // /workspace/config.py
170
171
// Check if absolute
172
console.log("Is absolute:", pyodide.PATH.isAbsolute("/workspace")); // true
173
console.log("Is absolute:", pyodide.PATH.isAbsolute("config.py")); // false
174
```
175
176
### Working with Python Files
177
178
```javascript
179
// Create Python module
180
pyodide.FS.writeFile("/workspace/mymodule.py", `
181
def calculate(x, y):
182
return x ** 2 + y ** 2
183
184
def greet(name):
185
return f"Hello, {name}!"
186
187
PI = 3.14159
188
`);
189
190
// Use the module in Python
191
pyodide.runPython(`
192
import sys
193
sys.path.append("/workspace")
194
195
import mymodule
196
197
result = mymodule.calculate(3, 4)
198
greeting = mymodule.greet("Pyodide")
199
200
print(f"Calculation result: {result}")
201
print(greeting)
202
print(f"PI value: {mymodule.PI}")
203
`);
204
```
205
206
### Node.js Host Directory Mounting
207
208
```javascript
209
// Mount host directory (Node.js only)
210
try {
211
pyodide.mountNodeFS("/host", "/path/to/host/directory");
212
213
// Access host files from Python
214
pyodide.runPython(`
215
with open("/host/data.txt", "r") as f:
216
content = f.read()
217
print("Host file content:", content)
218
219
# Write to host directory
220
with open("/host/output.txt", "w") as f:
221
f.write("Generated by Pyodide")
222
`);
223
224
console.log("Host directory mounted successfully");
225
} catch (error) {
226
console.error("Failed to mount host directory:", error.message);
227
}
228
```
229
230
### Browser File System Access
231
232
```javascript
233
// Request directory access (browser only)
234
async function setupWorkspaceAccess() {
235
try {
236
// Request directory picker
237
const dirHandle = await window.showDirectoryPicker();
238
239
// Mount the directory
240
const nativeFS = await pyodide.mountNativeFS("/workspace", dirHandle);
241
242
// Access files from the selected directory
243
pyodide.runPython(`
244
import os
245
files = os.listdir("/workspace")
246
print("Available files:", files)
247
248
# Read existing file if available
249
if "data.csv" in files:
250
import pandas as pd
251
df = pd.read_csv("/workspace/data.csv")
252
print("Data shape:", df.shape)
253
254
# Create new file
255
with open("/workspace/pyodide_output.txt", "w") as f:
256
f.write("Created by Pyodide in browser")
257
`);
258
259
// Sync changes back to native file system
260
await nativeFS.syncfs();
261
console.log("Files synced to native file system");
262
263
} catch (error) {
264
console.error("File system access denied:", error);
265
}
266
}
267
```
268
269
### Persistent Storage with IDBFS
270
271
```javascript
272
// Mount IndexedDB file system for persistence (browser only)
273
pyodide.FS.mkdir("/persistent");
274
pyodide.FS.mount(pyodide.FS.filesystems.IDBFS, {}, "/persistent");
275
276
// Sync from IndexedDB
277
pyodide.FS.syncfs(true, (err) => {
278
if (err) {
279
console.error("Failed to sync from IndexedDB:", err);
280
return;
281
}
282
283
// Work with persistent files
284
pyodide.runPython(`
285
import os
286
persistent_file = "/persistent/user_data.json"
287
288
if os.path.exists(persistent_file):
289
import json
290
with open(persistent_file, "r") as f:
291
data = json.load(f)
292
print("Loaded persistent data:", data)
293
else:
294
# Create initial data
295
import json
296
data = {"visits": 1, "last_visit": "2024-01-01"}
297
with open(persistent_file, "w") as f:
298
json.dump(data, f)
299
print("Created initial persistent data")
300
`);
301
302
// Sync to IndexedDB
303
pyodide.FS.syncfs(false, (err) => {
304
if (err) {
305
console.error("Failed to sync to IndexedDB:", err);
306
} else {
307
console.log("Data persisted to IndexedDB");
308
}
309
});
310
});
311
```
312
313
### File Streaming and Large Files
314
315
```javascript
316
// Handle large files efficiently
317
function writeFileInChunks(path, data, chunkSize = 1024 * 1024) {
318
const encoder = new TextEncoder();
319
const bytes = encoder.encode(data);
320
321
// Open file for writing
322
const fd = pyodide.FS.open(path, "w");
323
324
try {
325
let offset = 0;
326
while (offset < bytes.length) {
327
const chunk = bytes.slice(offset, offset + chunkSize);
328
pyodide.FS.write(fd, chunk, 0, chunk.length);
329
offset += chunkSize;
330
}
331
} finally {
332
pyodide.FS.close(fd);
333
}
334
}
335
336
// Create large file
337
const largeContent = "x".repeat(10 * 1024 * 1024); // 10MB
338
writeFileInChunks("/data/large_file.txt", largeContent);
339
340
// Read file in chunks
341
function readFileInChunks(path, chunkSize = 1024 * 1024) {
342
const stats = pyodide.FS.stat(path);
343
const fd = pyodide.FS.open(path, "r");
344
const chunks = [];
345
346
try {
347
let bytesRead = 0;
348
while (bytesRead < stats.size) {
349
const buffer = new Uint8Array(Math.min(chunkSize, stats.size - bytesRead));
350
const read = pyodide.FS.read(fd, buffer, 0, buffer.length);
351
chunks.push(buffer.slice(0, read));
352
bytesRead += read;
353
}
354
} finally {
355
pyodide.FS.close(fd);
356
}
357
358
// Combine chunks
359
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
360
const result = new Uint8Array(totalLength);
361
let offset = 0;
362
for (const chunk of chunks) {
363
result.set(chunk, offset);
364
offset += chunk.length;
365
}
366
367
return result;
368
}
369
```
370
371
### File System Utilities
372
373
```javascript
374
// Recursive directory listing
375
function listFilesRecursive(dirPath) {
376
const result = [];
377
378
function traverse(currentPath) {
379
const items = pyodide.FS.readdir(currentPath);
380
381
for (const item of items) {
382
if (item === "." || item === "..") continue;
383
384
const fullPath = pyodide.PATH.join(currentPath, item);
385
const stats = pyodide.FS.stat(fullPath);
386
387
if (pyodide.FS.isDir(stats.mode)) {
388
result.push({ path: fullPath, type: "directory" });
389
traverse(fullPath);
390
} else {
391
result.push({
392
path: fullPath,
393
type: "file",
394
size: stats.size,
395
modified: new Date(stats.mtime)
396
});
397
}
398
}
399
}
400
401
traverse(dirPath);
402
return result;
403
}
404
405
// Copy file with progress
406
function copyFileWithProgress(src, dst, progressCallback) {
407
const stats = pyodide.FS.stat(src);
408
const srcFd = pyodide.FS.open(src, "r");
409
const dstFd = pyodide.FS.open(dst, "w");
410
411
try {
412
const chunkSize = 64 * 1024; // 64KB chunks
413
let bytesCopied = 0;
414
415
while (bytesCopied < stats.size) {
416
const remaining = stats.size - bytesCopied;
417
const currentChunkSize = Math.min(chunkSize, remaining);
418
const buffer = new Uint8Array(currentChunkSize);
419
420
pyodide.FS.read(srcFd, buffer, 0, currentChunkSize);
421
pyodide.FS.write(dstFd, buffer, 0, currentChunkSize);
422
423
bytesCopied += currentChunkSize;
424
progressCallback?.(bytesCopied, stats.size);
425
}
426
} finally {
427
pyodide.FS.close(srcFd);
428
pyodide.FS.close(dstFd);
429
}
430
}
431
432
// Usage
433
copyFileWithProgress("/data/large_file.txt", "/backup/large_file.txt",
434
(copied, total) => {
435
const percent = (copied / total * 100).toFixed(1);
436
console.log(`Copy progress: ${percent}%`);
437
}
438
);
439
```
440
441
## File System Types
442
443
```javascript { .api }
444
interface FSStats {
445
dev: number;
446
ino: number;
447
mode: number;
448
nlink: number;
449
uid: number;
450
gid: number;
451
rdev: number;
452
size: number;
453
atime: Date;
454
mtime: Date;
455
ctime: Date;
456
blksize: number;
457
blocks: number;
458
}
459
460
interface NativeFS {
461
syncfs(): Promise<void>;
462
}
463
```