Ayush Kumar
Ayush Kumar

Reputation: 21

How to run a python script from HTML in google chrome?

I'm building a chrome extension and I want to run a python script which is in my PC on click of a button from an extension (which is basically HTML). The python script uses selenium web-driver to scrape data from a website and store it in another log file.

Upvotes: 1

Views: 5196

Answers (2)

ishandutta2007
ishandutta2007

Reputation: 18284

Th other option instead of using nativeMessaging is to use pyodide or pyscript

Pyodide:

Install:

npm i pyodide

Import:

const { loadPyodide } = require("pyodide");

Use:

async function main() {
  let pyodide = await loadPyodide();
  // Pyodide is now ready to use...
  console.log(pyodide.runPython(`
    import sys
    sys.version
  `));
};
main();

Upvotes: 0

Mohamed Mansour
Mohamed Mansour

Reputation: 40199

You basically use nativeMessaging. It allows you to create a communication bridge between your extension and an external process (such as python).

The way nativeMessaging works is by installing a host on your machine, and communicates to and from Chrome extension through stdin and stdout. For example:

Host in Python

This is how you write your nativeMessaging host in python, I have included the full example of this from the docs, but made it easier to understand with less code.

host.py

This is basically an echo server, respects stdin and stdout, makes sure it sends it as binary stream.

#!/usr/bin/env python

import struct
import sys
import os, msvcrt

# Set the I/O to O_BINARY to avoid modifications from input/output streams.
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

# Helper function that sends a message to the webapp.
def send_message(message):
   # Write message size.
  sys.stdout.write(struct.pack('I', len(message)))
  # Write the message itself.
  sys.stdout.write(message)
  sys.stdout.flush()

# Thread that reads messages from the webapp.
def read_thread_func():
  message_number = 0
  while 1:
    # Read the message length (first 4 bytes).
    text_length_bytes = sys.stdin.read(4)

    if len(text_length_bytes) == 0:
      sys.exit(0)

    # Unpack message length as 4 byte integer.
    text_length = struct.unpack('i', text_length_bytes)[0]

    # Read the text (JSON object) of the message.
    text = sys.stdin.read(text_length).decode('utf-8')

    send_message('{"echo": %s}' % text)


def Main():
    read_thread_func()
    sys.exit(0)

if __name__ == '__main__':
  Main()

host.json

This defines the communication python host, make sure the extension guid is the guid of your extension.

{
  "name": "com.google.chrome.example.echo",
  "description": "Chrome Native Messaging API Example Host",
  "path": "host.bat",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"
  ]
}

host.bat

This runs the python executable.

@echo off
python "%~dp0/host.py" %*

install_host.bat

You run this once, to register your host in your OS.

REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /ve /t REG_SZ /d "%~dp0host.json" /f

Chrome Extension

manifest.json

Add the permissions for nativeMessing

{
  "permissions": [
    "nativeMessaging"
  ]
}

communication.js

In order to connect to the python host, you need to do the following:

const hostName = "com.google.chrome.example.echo";
let port = chrome.runtime.connectNative(hostName);
port.onMessage.addListener(onNativeMessage);
port.onDisconnect.addListener(onDisconnected);

To send a message to your python host, just send a json object to the port.

const message = {"text": "Hello World"};
if (port) {
    port.postMessage(message);
}

To know the error when it disconnects:

function onDisconnected() {
  port = null;
  console.error(`Failed to connect: "${chrome.runtime.lastError.message}"`);
}

This full example is in the docs, I just renamed some stuff for clarity, available for Windows/Unix https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/docs/examples/api/nativeMessaging

Upvotes: 7

Related Questions