Inter Process Communication (IPC) with Electron and Python

Inter Process Communication (IPC) with Electron and Python

Electron is a great software framework for a software UI developer because its UI is basically a browser with a node server. So it is supporting all the JavaScript UI frameworks such as Angular, Vue, React, etc. For me, this is heaven because I’ll be able to develop software faster with a JavaScript UI.

But the backend of the software is always easy for me if it can be developed in python. So I’m going to create the backend process to be work as a service in the system that provides data to the UI and gets commands and data from the UI. Basically a client and a server on the same PC.

 

IPC with UI and Main Process of Electron

The Electron has two types of processes as might you already know as Main Process and Renderer Process. UI windows are generated in the Renderer Process and the communication with UI and the Main Process is done via an IPC library.

IPC inside Electron
IPC inside Electron

First of all, you need to import ipcMain into the main process.

import { app, protocol, BrowserWindow, ipcMain } from 'electron'

Then you need to import ipcRenderer into the UI component.

import { ipcRenderer } from 'electron'

Then you can use either the synchronous method or the asynchronous method to continue.

 

Synchronous Method

In the synchronous method, the process will wait for the reply.

In the main process, you need to create an event listener as follows.

ipcMain.on('get-data-sync', (event, arg) => {
    console.log(arg)
    event.returnValue = 'Test Data from the Main'
})

In here arg will contain the data that you have sent from the UI component.

In the UI component, you need to trigger the previously created event with a sync request as follows.

let response = ipcRenderer.sendSync('get-data-sync', 'Test Data from the UI')
console.log(response)

The response will contain the data sent from the main process.

 

Asynchronous Method

In the asynchronous method, the process will not wait for the data. Once the data is received, a separate event is triggered.

In the main process, you need to create an event listener as follows.

ipcMain.on('get-data-async', (event, arg) => {
    console.log(arg)
    event.reply('set-data-async', 'Test data from the Main')
})

In the above, arg will contain the data sent from the UI.

In the UI component also you need to create an event to get the reply from the main process as follows.

ipcRenderer.on('set-data-async', (event, arg) => {
    console.log(arg)
})

In the above, arg contains the data from the main thread.

Then you need to trigger the event in the main thread from the UI as follows.

ipcRenderer.send(get-data-async', 'Test data from the UI')

 

IPC with Electron and Python

When doing IPC with Electron and Python, I configured python to act as a server and electron to act as a client. This could be changed as your requirement.

Now I’, going to send the previously created request from UI to the main process to the python service and get the response back to UI.

IPC from UI to Python
IPC from UI to Python

 

Electron Prerequisites

You need to install socket.io-client package.

npm install socket.io-client

 

Python Prerequisites

You need to install eventlet and python-socketio packages.

pip install eventlet
pip install python-socketio

 

Python Code

In the python service, I’m going to open a socket and create events to be triggered from the Electron process.

import eventlet
import socketio

sio = socketio.Server()
app = socketio.WSGIApp(sio)

@sio.event
def connect(sid, environ):
    print('connect ', sid)

@sio.on('get-data-python')
def msg(sid, data):
    print('message ', data)

    return "OK", "Test data from python"

@sio.event
def disconnect(sid):
    print('disconnect ', sid)

if __name__ == '__main__':
    eventlet.wsgi.server(eventlet.listen(('', 5000)), app)

 

Electron Code

In the main process of the UI, you first need to open a connection to the above-created socket.

import { io } from "socket.io-client";

const socket = io("http://0.0.0.0:5000");

And then you need to trigger the event created in the python service as follows.

socket.emit('get-data-python', 'Test data from the UI', (err, res) => {
    console.log(res)
})

Since we’re going to combined UI to the main process code to the above, the final code will be as follows.

ipcMain.on('get-data-async', (event, arg) => {
    socket.emit('get-data-python', arg, (err, res) => {
        console.log(res)
        event.reply('set-data-async', res)
    })
})

And you will get a response from the python service to the UI and it should be used as you want.

So that’s it

If you have any suggestions or questions about this guide, comment here or send me an email.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top