skip to Main Content

Is it possible to run a python script from html code without any limitations

I am trying to create a combo of a webpage and a python script which lets users to scrape a particular website/s and display the information using requests module in python with the python script being executed from my server , in such a way that my webpage being the frontend and the python script being the backend

I tried using php with shell_exec function as shown in this answer but all it shows is a blank screen with the code being unexecuted in my browser

I also tried using pyscript but was unable to import python requests since it’s not in their supported packages

2

Answers


  1. There’s a library called Brython (https://brython.info/), it can help you somewhat, but of course consider that there are limitations.

    Here’s the example of how to send request to HTTP site:

    <html>
    
    <head>
        <meta charset="utf-8">
        <script type="text/javascript"
            src="https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js">
        </script>
        <script type="text/javascript"
            src="https://cdn.jsdelivr.net/npm/[email protected]/brython_stdlib.js">
        </script>
    </head>
    
    <body onload="brython()">
    
    <script type="text/python">
    from browser import ajax
    from browser import document
    
    query = ''
    url = 'http://www.http2demo.io/'
    
    def get_request(url, q):
        req = ajax.ajax()
        req.bind('complete', on_complete)
    
        req.open('GET', url+'?'+q, True)
        req.set_header('content-type', 'application/x-www-form-urlencoded')
        req.send()
    
    def on_complete(r):
        if r.status==200 or r.status==0:
           document <= r.text
        else:
            document <= "error: " + r.text
    
    get_request(url, query)
    </script>
    
    </body>
    
    </html>
    

    The better approach would be to create microservice, which would consist of front-end (user inputs URL to parse) and back-end (python logic – requests, etc.).

    Login or Signup to reply.
  2. Sure, I am no pro by any means but this is how I would do it.

    # main.py
    
    """ FastAPI endpoint that your front end can call to fire off your script """
    
    from fastapi import FastAPI
    from fastapi.middleware.cors import CORSMiddleware
    
    app = FastAPI()
    
    # Adjust your CORS settings as you need too
    # https://fastapi.tiangolo.com/tutorial/cors/
    
    origins = [
        "http://localhost.tiangolo.com",
        "https://localhost.tiangolo.com",
        "http://localhost",
        "http://localhost:8080",
    ]
    
    app.add_middleware(
        CORSMiddleware,
        allow_origins=origins,
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    
    
    @app.get("/")
    async def root():
        return {"message": "I am Root!"}
    
    @app.get("/api/name-your-endpoint")
    def some_func():
        # add your script here and pass anything you need as an argument
        pass
    

    With the above, you have a simple endpoint called http://localhost/api/name-your-endpoint for example. This can now be called by anything once it’s running. You could use fetch() or useEffect() depending if you’re going vanilla JS or React.

    Below is the Dockerfile I have used for one of my API projects, this is likely to be different for you but gives you an idea of what to expect. you can find more info here: https://fastapi.tiangolo.com/deployment/docker/

    Please bare in mind that this Dockerfile uses pipenv and not standard requirements.txt

    # DockerFile
    
    # For more information, please refer to https://aka.ms/vscode-docker-python
    FROM python:3.8-slim
    
    EXPOSE 80
    
    # Keeps Python from generating .pyc files in the container
    ENV PYTHONDONTWRITEBYTECODE=1
    
    # Turns off buffering for easier container logging
    ENV PYTHONUNBUFFERED=1
    
    # Install pip requirements
    COPY Pipfile Pipfile.lock ./
    RUN python -m pip install --upgrade pip
    RUN pip install pipenv && pipenv install --dev --system --deploy
    
    WORKDIR /app
    COPY . /app
    
    # Creates a non-root user with an explicit UID and adds permission to access the /app folder
    # For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
    RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
    USER appuser
    
    # During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
    CMD ["uvicorn", "main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "8080"]
    

    Now for the front end, I would use React if you know it, and build something like this, this will have the user call the end point via a button.

    // App.jsx
    
    // This component will use a button in the UI to call the endpoint and populate the data
    
    import { useState } from 'react'
    
    function App() {
    
       const [data, setData] = useState([])
    
       const generateDataFromEndpoint = async () => {
    
       try {
            await fetch(
              `${YOUR-HOST-BASE-URL}/api/api/name-your-endpoint`,
            )
              .then(res => res.json())
              .then(data => {
                setData(data)
                return true
              })
          } catch (error) {
            console.log(error)
          }
         }
    
          return (
            <> 
              <button onClick={generateDataFromEndpoint()}>Get data</button>
              
              {`display your data by mapping over the returned array`}
              <div>
                {data.map((d) => (
                  <div>{d.someDataFromReturnedObject}</div>
                ))}
              </div>
            </>
          )
    
    }
    

    Or you could use something like useEffect() where the client will call the endpoint when the component loads.

    // App.jsx
    
    import {useEffect, useState} from 'react'
    
    function App() {
      const [data, setData] = useState([])
    
      const generateDataFromEndpoint = async () => {
        try {
          await fetch(`${YOUR-HOST-BASE-URL}/api/api/name-your-endpoint`)
            .then(res => res.json())
            .then(data => {
              setData(data)
              return true
            })
        } catch (error) {
          console.log(error)
        }
      }
    
      useEffect(() => {
        generateDataFromEndpoint()
      }, [])
    
      return (
        <>
          {`display your data by mapping over the returned array`}
          <div>
            {data.map(d => (
              <div>{d.someDataFromReturnedObject}</div>
            ))}
          </div>
        </>
      )
    }
    

    Of if you’re using vanilla JS you can just use fetch() like so:

    const generateDataFromEndpoint = async () => {
        try {
          await fetch(`${YOUR-HOST-BASE-URL}/api/api/name-your-endpoint`)
            .then(res => res.json())
            .then(data => {
              setData(data)
              return true
            })
        } catch (error) {
          console.log(error)
        }
      }
    

    This might be over kill for what you need but this is how I have done it in the past and works very well. But you would need a way to host and run a Docker container for this to work.

    If you are using React you could look at something like Vite.JS and host it on something like Vercel

    Below I have included some links for your reference

    This is also this SO link How can I run a Python script in HTML?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search