能否强制PyFilesystem将文件系统设为单例以适配测试场景?
Yes, you absolutely can make this work! The key is to use monkey-patching to override PyFilesystem's open_fs function (and optionally the MemoryFS class) so that all requests for an in-memory filesystem return your pre-populated singleton instance.
Step 1: Create and Populate Your Singleton Filesystem
First, set up your in-memory filesystem with all the test data you need:
from fs.memoryfs import MemoryFS # Create the singleton and populate test files _test_fs = MemoryFS() # Add your test content here with _test_fs.open("/sample_data.txt", "w") as f: f.write("This is pre-loaded test content!") _test_fs.makedirs("/test_dir") with _test_fs.open("/test_dir/nested_file.txt", "w") as f: f.write("Nested test file content")
Step 2: Monkey-Patch open_fs to Return the Singleton
Next, override the default open_fs function so that any call requesting a mem:// filesystem returns your singleton. You can also choose to force all filesystem requests to use the singleton (adjust the logic based on your testing needs):
from fs import open_fs # Save the original function in case you need to revert later original_open_fs = open_fs def patched_open_fs(url="fs://", *args, **kwargs): # Return our singleton for any mem:// URL if url.startswith("mem://"): return _test_fs # For other URLs, fall back to the original open_fs (optional) return original_open_fs(url, *args, **kwargs) # Replace the original open_fs with our patched version import fs fs.open_fs = patched_open_fs
Step 3: (Optional) Patch MemoryFS Directly
If uncontrolled code might instantiate MemoryFS directly (instead of using open_fs), you should also patch the MemoryFS class to return your singleton:
original_memory_fs = MemoryFS def patched_memory_fs(*args, **kwargs): return _test_fs # Replace the MemoryFS class from fs import memoryfs memoryfs.MemoryFS = patched_memory_fs
Key Considerations
- Patch Early: Make sure you apply these patches before importing or running any code that uses PyFilesystem. If other modules import
open_fsorMemoryFSbefore your patch, they'll use the original versions. - Clean Up After Testing: If you're using a test framework like pytest, use fixtures to automatically apply and revert the patches to avoid cross-test contamination. Example fixture:
import pytest from fs import open_fs, memoryfs @pytest.fixture(autouse=True) def singleton_test_fs(): # Create and populate the singleton test_fs = memoryfs.MemoryFS() with test_fs.open("/test_file.txt", "w") as f: f.write("Test content") # Save original implementations original_open = open_fs original_memory_class = memoryfs.MemoryFS # Apply patches def patched_open(url="fs://", *args, **kwargs): if url.startswith("mem://"): return test_fs return original_open(url, *args, **kwargs) memoryfs.MemoryFS = lambda *args, **kwargs: test_fs fs.open_fs = patched_open yield test_fs # Revert patches after test completes fs.open_fs = original_open memoryfs.MemoryFS = original_memory_class
With this setup, any call to open_fs("mem://...") or MemoryFS() will return your pre-populated singleton, regardless of where the call comes from.
内容的提问来源于stack exchange,提问作者David Parks

