How to copy / download file created in Pyodide in browser?
Asked Answered
S

2

8

I managed to run Pyodide in browser. I created hello.txt file. But how can I access it.
Pyodide
https://github.com/iodide-project/pyodide/blob/master/docs/using_pyodide_from_javascript.md

pyodide.runPython('open("hello.txt", "w")')

What I tried in chrome devtools?

pyodide.runPython('os.chdir("../")')
pyodide.runPython('os.listdir()')
pyodide.runPython('os.path.realpath("hello.txt")')

Output for listdir

["hello.txt", "lib", "proc", "dev", "home", "tmp"]

Output for realpath

"/hello.txt"

Also,

pyodide.runPython('import platform')
pyodide.runPython('platform.platform()')

Output

"Emscripten-1.0-x86-JS-32bit"

All outputs in chrome devtools console.

It is created in root folder. But how it can be accessed in file explorer or anyway to copy file to Download folder?

Thanks

Stillborn answered 3/11, 2020 at 19:29 Comment(2)
emscripten.org/docs/api_reference/Filesystem-API.htmlStillborn
I am finding solution and got this. May be helpful groups.google.com/g/emscripten-discuss/c/xnTzhcsMj4U?pli=1Stillborn
P
7

Indeed pyodide operates in an in-memory (MEMFS) filesystem created by Emscripten. You can't directly write files to disk from pyodide since it's executed in the browser sandbox.

You can however, pass your file to JavaScript, create a Blob out of it and then download it. For instance, using,

let txt = pyodide.runPython(`                  
    with open('/test.txt', 'rt') as fh:
        txt = fh.read()
    txt
`);
const blob = new Blob([txt], {type : 'application/text'});
let url = window.URL.createObjectURL(blob);
window.location.assign(url);

It should have been also possible to do all of this from the Python side, using the type conversions included in pyodide, i.e.

from js import Blob, document
from js import window
  
with open('/test.txt', 'rt') as fh:
    txt = fh.read()
    
blob = Blob.new([txt], {type : 'application/text'})
url = window.URL.createObjectURL(blob) 
window.location.assign(url)

however at present, this unfortunately doesn't work, as it depends on pyodide#788 being resolved first.

Palpable answered 3/11, 2020 at 20:24 Comment(5)
Then it is also possible to send file from local browser to MEMFS?Stillborn
If I understand your question correctly, yes, you can also get any object, including a representation of a File, from JS to Python and then write it to MEMFS there pyodide.readthedocs.io/en/latest/…Palpable
any update on this ? I'm very interested in the solution to save tmp filesPleochroism
The link to the documentation by @Palpable in the comment above dated Nov2'20 20:51 is outdated. I think it should be pyodide.org/en/latest/usage/… now.Nicotinism
This now works for me in firefox running osx sonoma 14.1Decidua
S
3

I have modified the answer by rth. It will download file with the name of file.

let txt = pyodide.runPython(`                  
    with open('/test.txt', 'rt') as fh:
        txt = fh.read()
    txt
`);

const blob = new Blob([txt], {type : 'application/text'});
let url = window.URL.createObjectURL(blob);

var downloadLink = document.createElement("a");
downloadLink.href = url;
downloadLink.download = "test.txt";
document.body.appendChild(downloadLink);
downloadLink.click();
Stillborn answered 3/11, 2020 at 21:18 Comment(1)
Although technically, this assumes a lot more than @Palpable answer, I like it.Decidua

© 2022 - 2024 — McMap. All rights reserved.