ModuleNotFoundError after writing multiple files with FS.writeFile
See original GitHub issue🐛 Bug
This might be a duplicate of #737, but I’m opening a new issue because I’m seeing something very weird. I’m using Pyodide 0.21.3.
To Reproduce
Consider the following snippet (I run it in node, but I can reproduce the same behavior also in the browser):
const { loadPyodide } = require("pyodide");
function busyWait(ms) {
let start = new Date().valueOf();
while( (new Date()).valueOf() - start < ms)
;
}
async function main() {
let pyodide = await loadPyodide({
indexURL: "./node_modules/pyodide",
});
console.log("Pyodide version: ", pyodide.version);
let success = 0;
let errors = 0;
for(let i=0; i<100; i++) {
// uncommenting EITHER of the following lines, it works reliably
//pyodide.runPython('import importlib; importlib.invalidate_caches()');
//busyWait(1000);
pyodide.FS.writeFile(`bar${i}.py`, `x = ${i}`);
try {
pyodide.runPython(`import bar${i} as bar; print('OK ', bar.x)`);
success++;
}
catch(e) {
//console.log(e);
console.log('ERR', i);
errors++;
}
}
console.log("success:", success);
console.log("errors :", errors);
console.log("error rate: ", (errors/(success+errors))*100, "%");
}
main();
The expected result is obviously to see all OK
and 0% error rate, but what happens is that very often I get ERR
.
I observed the following:
- if I uncomment the call to
invalidate_caches()
, it passes reliably - if I uncomment
busyWait(1000)
, (i.e., 1 second) it passes reliably
The interesting part is what happens with lower values of busyWait
:
- with
busyWait(500)
, it fails ~50% of the times - with
busyWait(100)
it fails ~90% of the times - with
busyWait(10)
it fails ~99% of the times
The following is just a guess, but I think that considering the above it’s a reasonable explanation:
- somewhere there is a timestamp which is stored with a resolution of 1s
- if the “new” files are written “too early”, importlib think that it is of the same epoch as the “old files/directories” and thus it thinks the cache is still valid
- if you wait long enough, the 1s timestamp gets a new value and importlib correctly notices that there is a “new” file
I am not sure whether this is a bug/“feature” of emscripten. I thought it’s a good idea to open it here so that we can maybe discuss possible pyodide-specific mitigations and/or workarounds
Issue Analytics
- State:
- Created 10 months ago
- Reactions:2
- Comments:25 (25 by maintainers)
Top Results From Across the Web
nodejs: write multiple files in for loop - javascript - Stack Overflow
I want to write a number of files and when it is all done continue on other task. Without for loop, I am...
Read more >Module not found: Can't resolve 'fs' · Issue #7755 · vercel/next.js
I'm using the popular find-up npm package, which has locate-path as a dependency. locate-path requires fs within it's code. When I attempt to ......
Read more >ModuleNotFoundError: no module named Python Error [Fixed]
When you try to import a module in a Python file, Python tries to resolve this module in several ways. · As the...
Read more >How to write to files with Node.js - Emma Goto
In this post we'll be covering how you can use the fs module in Node.js to write to and modify files with writeFile()...
Read more >Python – Import module from different directory - GeeksforGeeks
ModuleNotFoundError, because by default Python interpreter will check for the file in the current directory only, and we need to set the file...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Great! Thanks sound indeed promising.
BTW, even if we make
st_mtime_ns
available in Pyodide, I guess we have to persuade CPython devs to usest_mtime_ns
instead ofst_mtime
here?I was able to observe the similar result in native Python (tested in Linux):