How to use Python with Node.js

Dan Beech
Python in Plain English
5 min readFeb 17, 2021

--

Sometimes you find yourself in a situation where Python would be a better option than Node for getting a job done.

I’ve encountered this while creating desktop apps with Electron.js that interact with microcontrollers, and I’ve created web APIs to interact with existing Python scripts. Regardless of your scenario, it’s a useful tool to have in your arsenal, so here’s how I usually do it.

Photo by Maxwell Nelson on Unsplash

In this article we will create a simple program using Node.js and Python. The JS will call the Python, get the output of the script and return it to JS.

First let’s create a simple Python script that has a single argument, we will print out whatever value is provided with that argument, and then print out some generic messages afterwards:

As you can see we have the argument ‘ — hello’ and we print the value of this argument on line 8. From line 10 onwards we’re just printing some generic strings out. We add flush=True to the prints, and a sleep to ensure that the output isn’t buffered. If you go ahead and remove the ‘flush=True’ from the first print, you will see that the output for the first and second prints are returned together. The same happens if you remove the sleep. I usually use a sleep of 0.05, but I’ve exaggerated it here.

Buffered output can be useful in some cases, but most of the time I’ve wanted my output separated so that I can use each separate print to trigger actions in my Node.js programs. There are other ways (inside Python, or in the spawn of the child process) to make the output unbuffered, but for this article we’re using the most obvious way of doing it.

A note for Electron.js users: Whenever I’ve used a Python child process inside an Electron app I’ve had to add a small sleep (0.05) after each print in the Python script or the output will be buffered, whether you tell it to be unbuffered or not. If this is the case you will often receive prints mixed together with others and it can mess with the functionality of your apps. So add your sleeps!

We can test that the script works by running it with:
python python.py --hello “Hello world!”

And we will get the output (with the delays we added):
Hello world!
I am talking from Python
I really like Python
But JS is cool too

Photo by Christina @ wocintechchat.com on Unsplash

Great! The Python script is working, so now how do we call it from inside Node.js?

Create a file called main.js, and inside it add the following code:

First we require ‘child_process’, this is part of Node.js that allows you to create, or to use another, more relevant word; spawn, a subprocess.

Before we spawn our child process, however, we want to push our arguments to it.

On line 3 we make a new array called args, and initialise it with one element; a string containing the name of the Python script we want to run, in this case that is ‘python.py’.

Next we push our script arguments to the array; so we push ‘ — hello’, and it’s value ‘Hello World’.

Line 6 is where we actually spawn the subprocess that runs the Python script. I’ve named it childProcess because it makes the rest of the code more readable and easy to understand. When we spawn the subprocess, we are giving it two values:

  • You will remember that we executed the script on it’s own by using python python.py --hello “Hello world!”.
    Here we are giving the cmd that is required to run the script in a terminal as the first argument; in this case ‘python’. This could change to ‘python3’ depending on your system.
  • Next we are providing the args array that we created.

Now that the subprocess is spawned with it’s arguments, we need to handle its output so that it can be returned to Node.

On line 8 we set the encoding for childProcess.stdout. This will be where the output of the Python script is returned to.

Line 9 is where we handle that output. If we read the words of this line backwards you can almost make a readable sentence out of it: data — on — stdout — childProcess.

Let’s fill in some gaps and we have a sentence that says exactly what it does: The data received on the stdout of the childProcess.

I’ve interpolated the data into a string so that when we run the child process script we will see the difference; that it is now printing from inside Node, and not Python.

On lines 13–16 we do the same, but this code handles the errors that may occur in the Python script. We can then handle those differently in Node so our programs are responsive and provide accurate user feedback.

Lastly, line 18–20 handles what happens when the Python script has finished its execution. Here we just print that it has finished.

Let’s test out the program! We can now run our Node.js code with:

node main.js

And we will see a different output in the terminal:

Node output: Hello World

Node output: I am talking from Python

Node output: I really like Python

Node output: But JS is cool too

Your Python and Node code should now be connected. You can also use the stdin to send information from Node to Python but I haven’t used that too much. You can read more into child processes here.

Photo by Nastya Dulhiier on Unsplash

Final tips

You can add markers to your Python prints and check for them when you handle them in your Node code. A habit I picked up from a friend of mine was to add [-] to the front of your prints for messages that won’t trigger actions and should just print to the console, and [+] for actions that will trigger actions. This allows easy string checking and makes it easier to debug and read your code when you need to maintain it.

If you need to compile the python script to a .exe to bundle it with your software then you can do so easily with auto-py-to-exe. Usually I do this when including Python child processes in Electron.js apps.

That’s a very basic implementation, but this functionality allows you to do very powerful things if you use it correctly. Try it out and let me know what you created! Thanks for reading :)

--

--

Flutter Engineer @ Bloom Money 🌱. Liverpool, UK. Enjoy mobile development with a focus on UI/UX implementation 🧑‍💻