This will be the first of several articles that provides details on Pyscript files and file systems. I will discuss the different virtual file systems and how to access files located on the desktop.

I have put each example in this article on my website. My examples can be downloaded using wget, curl , or by right-clicking on the page and selecting view page source. You can also right-click on the link and select Save link as.

Examples:

  • Example 1 – Test file access #1
  • Example 2 – Test file access #2
  • Example 3 – Display a file from the local file system
  • Example 4 – Display an image from the local file system

Part 2 of this series.

Terms:

  • Local File System

    • This is the computer’s file system that the browser loads from. The browser security model prohibits web applications from directly accessing the local file system. Allowing direct access would be a serious security problem.
  • Virtual File System

    • This is the file system that runs inside the browser. There are several types. The default type that is set up when a web page loads is transient. This means that any data stored in that file system is lost on page refresh. There are persistent file systems available for mounting.

Pyscript supports the Python Standard Library File and Directory APIs. These APIs access storage within the Virtual File System.  The virtual file system is provided by Emscripten File System API. Pyscript maps the Python Standard Library File and Directory APIs onto the Emscripten File System API.

PyScript Boilerplate HTML

For this article, I will use the following boilerplate. In the examples, I will only include the parts between the <py-script> tags.

Accessing the Virtual File System

The first step is to understand the concept of the current working directory. This will be the default location where files created by a Python application are stored.

You can try this example on my website [link].

The results of os.getcwd() are:

What is pyodide? Pyodide (pie-o-dide) is the framework/library that PyScript is built upon. They chose to name the default directory /home/pyodide.

Let’s look at what is stored in the root directory /.

Results:

Interesting, that looks like a basic Linux system.

If we list the contents of the /dev directory, we will find some interesting files listed:

Results:

Let’s create a file in the current working directory. Then read the file and print the contents.

Results:

Creating, writing, and reading normal files is easy to do. Experienced Python developers would improve the code so that file handles are closed automatically.

Storage Quota

You might ask, how much storage space is available in this virtual file system? Browsers such as Chrome establish quotas for virtual file system usage. On my test system, I only have 128 GB free, but Chrome allows for 614 GB. The 614 GB is per origin. The quota is based upon total disk space and not free space. Each browser sets its own formula for storage quotas. Poorly designed web applications can abuse a browser’s file system.

Link to Chrome documentation:

Chrome: Understanding storage quota

Storage Persistence

Let’s start with a new example. This time, we will list the content of the current directory and then check if filename.txt exists. If it does, display its contents. If not, then create it. This will test if a page refresh causes files to be lost.

You can try this example on my website [link].

Results:

Refresh the page and the same results are displayed. Files are not persisted on page reloads.

Why is data not persisted? The default virtual file system is based upon FS.MEMFS. MEMFS is a memory file system. I will cover virtual file system types in Part 3.

What can you do if you want to store persistent data? This is an important feature that can improve web applications.

There are two options:

  • Store persistent data in the local file system. I will discuss that in Part 2.
  • Store persistent data in the virtual file system. I will cover that in Part 3 where I will introduce the FS API and the types of virtual file systems. One type (FS.IDBFS) is based upon IndexedDB which is persistent.

Reading files from the local file system

Accessing files on the local file system cannot be performed directly by Python or JavaScript applications. By directly I mean the application must request access from the browser which then displays the file browse dialog. This requires human interaction and is a security feature to prevent applications from accessing local files without the user’s permission.

A new feature that is in development could change how the local file systems are accessed. I am not covering the new feature as it is not a standard yet and is mostly Chrome specific. The new API requires a user’s approval but the API interaction is much better for the application. Read more about this new feature at this link:

The File System Access API: simplifying access to local files

The first step is to create an HTML element that the user can select to start the file selection process:

That creates the standard HTML control similar to this screenshot:

Next, we need to wire up a Python function that will receive a callback when the user completes selecting a file after clicking the Choose File button. When the function process_file() is called, the event parameter contains information about the file that the user selected. This function proceeds and reads the file data from the browser.

There is one important package to import: asyncio. Without that package, you will see error messages in the browser console that are hard to understand. The key to remember is that the browser is asynchronous. That means we need to write callback functions with the async keyword.

Python functions cannot be called directly by the browser. A special proxy must be created. The browser calls the proxy which then calls the Python function. The proxy manages the translation of data types from the browser’s internal structure to ones Python understands and vice versa.

Let’s put that into a complete example including HTML so that everything makes sense. You can try this example on my website [link].

That example covers the basics of reading files from the local file system. There are more advanced details, but this will get you started. I recommend reading the documentation for the FileReader class. I will show another example, this one reads images from the local file system and displays them on a webpage. This demonstrates another FileReader API readAsDataURL(). You can try this example on my website [link].

Summary

The examples in this article show how to access one type of the virtual file system (MEMFS) and how to read files from the local file system. I have not gone into advanced details on these methods. I will cover more advanced topics in the next parts of this series on Pyscript Files and File Systems.

More Information

Photography Credit

I write free articles about technology. Recently, I learned about Pexels.com which provides free images. The image in this article is courtesy of Djalma Paiva Armelin at Pexels.