Search code examples
pythonpyscript

PyScript: is it possible to execute an uploaded Python script?


Is it possible to have a user upload an arbitrary Python script (that uses built-ins only, no external packages) and then execute it using PyScript?


Solution

  • You can use an HTML <input> element to upload the file, and use await file.txt() to get the source. Then there are a couple ways to execute the code.

    Using Python's exec() method:

    <script defer src="https://pyscript.net/releases/2022.12.1/pyscript.js"></script>
    <link rel="stylesheet" href="https://pyscript.net/releases/2022.12.1/pyscript.css">
    
    <input type="file" id="file-upload">
    
    <py-script>
        import js
        from pyodide.ffi.wrappers import add_event_listener
    
        async def upload_and_run(event):
            file_list = event.target.files
            first_item = file_list.item(0)
    
            src = await first_item.text()
            exec(src)
    
        input_elem = js.document.getElementById("file-upload")
        add_event_listener(input_elem, "change", upload_and_run);
    </py-script>
    

    Or, if you want the script to behave like a <py-script> tag, with pretty error handling and such, you could add source to a new <py-script> tag:

    <script defer src="https://pyscript.net/releases/2022.12.1/pyscript.js"></script>
    <link rel="stylesheet" href="https://pyscript.net/releases/2022.12.1/pyscript.css">
    
    <input type="file" id="file-upload">
    
    <py-script>
        import js
        from pyodide.ffi.wrappers import add_event_listener
    
        async def upload_as_script_tag(event):
            file_list = event.target.files
            first_item = file_list.item(0)
    
            src = await first_item.text()
            newTag = js.document.createElement("py-script")
            newTag.innerText = src
            js.document.body.appendChild(newTag)
    
        input_elem = js.document.getElementById("file-upload")
        add_event_listener(input_elem, "change", upload_as_script_tag);
    </py-script>
    </body>