Interactive Python interpreter for executing commands within Node.js

Overview

Python Interactive

CI Status Coverage Status Node

Interactive Python interpreter for executing commands within Node.js.

This module provides a means of using the Python interactive interpreter programmatically from within Node.js, allowing commands to be executed from code as if they were being run in a terminal.

Commands are executed asynchronously through the use of async/await, with results being returned via a Promise. This allows for interactions to be handled differently depending on whether the Python code ran successfully or returned an error.

Example

let {PythonInteractive} = require('python-interactive');
let python = new PythonInteractive();

let loopCmd = `
count = 0
while pi > 0:
  pi = pi / 2
  count += 1

print(count)
`;

// Start the Python process
python.start();

await (async () => {
  // Import packages and ignore any output
  await python.execute('from math import pi');

  // Print value of 'pi' and store the output
  let pi = await python.execute('print(pi)');

  // Execute multiline loop command and handle its output via Promise callbacks
  await python.execute(loopCmd)
    .then((data) => {
      // If the Python code executed successfully
      console.log(`${pi} was halved ${data} times before being less than or equal to 0`);
    })
    .catch((err) => {
      // If the Python code executed with an error
      console.log(`Failed to execute due to error:\n ${err}`);
    })
})();

// Stop the Python process
python.stop();
3.141592653589793 was halved 1077 times before being less than or equal to 0

Usage

Installing

NPM

Loading the Module

// ES6 module syntax
import {PythonInteractive} from 'python-interactive';

// CommonJS module syntax
let {PythonInteractive} = require('python-interactive');

Use ES6 import or CommonJS require to use the PythonInteractive class.

Creating an Instance

// Use default Python executable
let python = new PythonInteractive();

// Use specific Python executable
let python = new PythonInteractive('python3.9');

// Use specific Python executable with path
let python = new PythonInteractive('/path/to/python');

Create a new instance of PythonInteractive. By default, the Python interpreter will be spawned in interactive mode and is called using the python3 command on Unix systems or python on Windows. You must have Python in your PATH for this to work.

Each instance of PythonInteractive maintains a single isolated Python interpreter process. This allows you to have multiple Python processes running simultaneously whilst ensuring that they do not interfere with one another.

Optionally, you can initialise the Python interpreter using a specific Python executable. This can be done by passing in a path or command to the constructor.

Starting a Python Process

python.start();

To start the Python process, call the start() method. Attempting to execute commands before calling start() will result in an error being thrown. This method will not do anything if a process is already running.

Stopping a Python Process

python.stop();

To stop the Python process, call the stop() method. This will destroy all stdio streams, kill the Python process, then set it to null. When stop() is run, commands can no longer be executed until start() is called again. This method will not do anything if a process is not running.

Restarting a Python Process

python.restart();

To restart the Python process, call the restart() method. This method acts as a wrapper for calling stop() and then start(), and provides no additional functionality.

Executing Commands

Commands can be executed in multiple ways, but should always be done using async/await functionality as the result is returned via a Promise. Below are some examples of how commands can be executed. For more examples, take a look at the test suite.

Ignore Output

(async () => {
  await python.execute('x = 10');
})();

This will execute a command but do nothing with its output. However, in this example the x variable will still be assigned the value 10, and can be referenced in future command executions. Note that if a command is executed in this manner and causes an error, the error will be thrown (this can be handled using try/catch or the catch() function).

Retrieve Output

(async () => {
  let result = await python.execute('print(x)');
})();

This will execute a command and then save its output to the result variable. Since x was previously assigned the value 10, executing the command print(x) will give the output 10. This value is then saved to result. Note that if a command is executed in this manner and causes an error, the error will be thrown (this can be handled using try/catch or the catch() function).

Handle Output

(async () => {
  await python.execute('print(y)')
    .then((data) => {
      console.log(`Executed successfully with output:\n ${data}`);
    })
    .catch((err) => {
      console.log(`Failed to execute with error:\n ${err}`);
    })
})();

This will execute a command and then handle the output by attaching callbacks to the returned Promise. If the command executes without an error, the then() callback will handle the output. If the command returned an error, the catch() callback will handle the output. In this example, the catch() callback will be executed (as y has not been declared) and output the following:

", line 1, in NameError: name 'y' is not defined">
Failed to execute with error:
Traceback (most recent call last):
  File "
     
      ", line 1, in 
      
       
NameError: name 'y' is not defined

      
     

Multiline Command

let input = `
i = 0
while i < 3:
  print(i)
  i += 1

print(i*i)
`;

(async () => {
  let result = await python.execute(input);
  console.log(`"${result}"`);
})();

It is also possible to execute multiline commands, with any output being concatenated into a single string. For example, the above code will return the output:

"0
1
2
9"

Multiline constructs (e.g. loops, functions, classes) must be closed before the code can be executed - you cannot execute separate parts of a construct individually.

Interpreter Rules

Note that you must adhere to the rules of the Python interpreter when in interactive mode; indentation and line breaks must be used correctly to represent where constructs end. For example, this is valid Python code:

for i in range(a):
  print(i)

print(i * i)

This is not valid Python code and will return an IndentationError:

for i in range(a):
  print(i)
print(i * i)

API

PythonInteractive(pythonPath)

Initialises a new instance of PythonInteractive.

Each instance of PythonInteractive uses its own process, separate from all other instances. Note that the Python process is not spawned until the start() method is called.

Parameters

  • pythonPath (string): path to the Python interpreter. Defaults to python3 on Unix systems or python on Windows.

Properties

  • pythonPath (string): path to the Python interpreter.
  • process (ChildProcess): the current Python interpreter process.
  • history (Array ): all commands that have been executed for the current process.
  • lastCommand (string): the last command that was executed for the current process.

start()

Spawns a new Python process.

A new process is spawned using the Python interpreter as defined by the pythonPath property, though only if no process is currently running. To kill the current process, call stop(). Note that the history property is reset when calling this method.

The Python interpreter is always spawned with the -i, -u, and -q flags.

Parameters

  • args (string[]): Arguments to pass to the Python interpreter.
  • options (Object): Options to pass to the spawned process.

stop()

Kills the current Python process.

If no process is running, this method will do nothing. To spawn a new process, call the start() method.

restart()

Kills the current Python process and spawns a new one.

This method acts as a wrapper for executing stop() and then start(). It will only kill a process if there is a process currently running. If not, then only a new process is spawned. Note that the history property is reset when calling this method.

Parameters

  • args (string[]): Arguments to pass to the Python interpreter.
  • options (Object): Options to pass to the spawned process.

pythonVersion()

Returns the version of the Python interpreter via a Promise.

pythonBuild()

Returns information about the Python interpreter build via a Promise.

This method only works with Python 3.6 or greater.

execute(command)

Executes a string of Python code and returns the output.

Before commands can be executed, the Python process must be spawned using the start() method. An error will be thrown if the Python process has not been started.

Returns a Promise which will resolve with the output if the command executed successfully, or reject with an error message if the command failed.

Parameters

  • command (string): Python command to be executed. May be a single command or multiple commands separated by line breaks. If undefined, an empty line is executed.
You might also like...
commandpack - A package of modules for working with commands, command packages, files with command packages.
commandpack - A package of modules for working with commands, command packages, files with command packages.

commandpack Help the project financially: Donate: https://smartlegion.github.io/donate/ Yandex Money: https://yoomoney.ru/to/4100115206129186 PayPal:

Output Analyzer for you terminal commands
Output Analyzer for you terminal commands

Output analyzer (OZER) You can specify a few words inside config.yaml file and specify the color you want to be used. installing: Install command usin

A terminal tool for git. When we use git, do you feel very uncomfortable with too long commands
A terminal tool for git. When we use git, do you feel very uncomfortable with too long commands

PIGIT A terminal tool for git. When we use git, do you feel very uncomfortable with too long commands. For example: git status --short, this project c

⚙ A lightweight command line interface library for creating commands.
⚙ A lightweight command line interface library for creating commands.

⚙ A lightweight command line interface library for creating cli commands. About | Installation | Usage | Features | Contributors | License About Next:

tox-server is a command line tool which runs tox in a loop and calls it with commands from a remote CLI.

Tox Server tox-server is a command line tool which runs tox in a loop and calls it with commands from a remote CLI. It responds to commands via ZeroMQ

A CLI for advanced management of your notes with simple commands

PyNoteManager This is a CLI for advanced management of your notes with simple co

Message commands extension for discord-py-interactions

interactions-message-commands Message commands extension for discord-py-interactions README IS NOT FINISHED YET BUT IT IS A GOOD START Installation pi

A Multipurpose bot with many Commands made using Pycord

This repo has all of the commands you will ever need in a discord bot. a Multipurpose discord bot

A Bot Which Send Automatically Commands To Karuta Hub to Gain it's Currency

A Bot Which Send Automatically Commands To Karuta Hub to Gain it's Currency

Comments
  • Parallel instance commands tests throw '>>>'

    Parallel instance commands tests throw '>>>'

    Bug Description

    Quite rarely, tests involving parallel instanced commands will thrown >>> as an error.

    Steps to Reproduce Bug

    This can be most easily seen by repeatedly running the unit tests involving parallel instanced commands, and usually occurs with the Execute_ParallelInstancedMixedCommands_ReturnsErrorsAndOutputs test.

     Execute Python Commands › Async Commands › Execute_ParallelInstancedMixedCommands_ReturnsErrorsAndOutputs
        thrown: ">>>"
    

    Additional Information

    Jest will not exit when this error occurs, meaning that there are asynchronous operations that weren't stopped in the tests.

    System Information

    • Node.js Version: 16.6.1
    • Operating System: Arch Linux 5.13.9
    bug 
    opened by louislefevre 1
  • Incomplete error messages

    Incomplete error messages

    Bug Description

    Sometimes, errors output by the PythonShell are partially or entirely incomplete. As a result, unit tests related to testing errors are flaky and will sometimes arbitrarily fail.

    Steps to Reproduce Bug

    This can be most easily seen by repeatedly running the unit tests until one of the ones related to invalid commands/returning errors breaks.

    Expected Behaviour & Actual Behaviour

    Expected:

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'x' is not defined
    

    Actual:

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    

    Additional Information

    This problem is due to the Python process stdout listener resolving its promise too fast. Only one stream, out of stdout and stderr, can be read at one time. The listener for stdout is where it is determined whether or not all the data has been received. If stdout is being read and completes, the promise will resolve with any information it currently has, even if not all information has been read from stderr. The solution to the problem is to implement a method for ensuring that both streams have been fully read in before resolving the promise.

    System Information

    • Node.js Version: 16.5.0
    • Operating System: Arch Linux 5.13.5
    bug 
    opened by louislefevre 0
Releases(v0.3.2)
  • v0.3.2(Sep 10, 2021)

    • c82a66e69f232bd16f9300dc83961bba60102b1b - Update dependencies to latest versions
    • b940f230dd59274fc01c1bd11606008201591521 - Add cross-spawn dependency for more reliable process spawning on Windows
    • 5d93333aa64f86210616a58debca4a14ea7ba209 - Update how prompts are handled; they are now removed when the process is spawned rather than filtered out from the output, fixing random >>> prompts sometimes being thrown as errors
    • 7c6db7b48daf7c8d4ea15215a670432a44d93183 - Remove ts-replace-all dependency
    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Aug 28, 2021)

    • b3bcc1f5c8037ed39b28c01d52d930d8e341c12a - Fix streams blocking execution when they unexpectedly end or return an error
    • 43039503cd16bd3c02a0ed813a16589fb71caa8c - Fix trailing arrows being returned (usually on Windows)
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Aug 21, 2021)

  • v0.2.0(Aug 12, 2021)

    • d4e755495aec944d4eb81aa3193e5f5c26ea3912 - Compile to ECMAScript 2019 instead of ECMAScript 2015
    • 94ca5a6ec4e726fc5b17f7ccb713d995b9f61932 - Add lastCommand property
    • a739381cb903a58e5ceb02a13c64424a67b021ea - Add pythonVersion() method
    • 535cc5d4c08c0a595e13ed64cc64ee9f2e313e6f - Add pythonBuild() method
    • f225b9bb504e13c83df871c7305e76c31e116dfc - Remove async from start() and restart() methods so that they no longer return interpreter build information
    • ff5059ae67b15800d91304c11fd6390ffab6375c - Remove script property, add history property
    • d99803a3b1129ff69cf43ccb53646c2d377825a9 - Update documentation to be up-to-date
    Source code(tar.gz)
    Source code(zip)
  • v0.1.1(Aug 9, 2021)

    1f9d787ea35734081884369bbdadb23b3e936281 - Update README.md to include execute() function in API section e5bef7932a5a267e1520b1c34b2c8ee691a3af9f - Fix error messages not always being displayed in full (#1)

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Aug 4, 2021)

A command-line utility that creates projects from cookiecutters (project templates), e.g. Python package projects, VueJS projects.

Cookiecutter A command-line utility that creates projects from cookiecutters (project templates), e.g. creating a Python package project from a Python

18.6k Dec 30, 2022
instant coding answers via the command line

howdoi instant coding answers via the command line Sherlock, your neighborhood command-line sloth sleuth. Are you a hack programmer? Do you find yours

Benjamin Gleitzman 9.8k Jan 08, 2023
py-image-dedup is a tool to sort out or remove duplicates within a photo library

py-image-dedup is a tool to sort out or remove duplicates within a photo library. Unlike most other solutions, py-image-dedup intentionally uses an approximate image comparison to also detect duplica

Markus Ressel 96 Jan 02, 2023
Command Line For Truecaller Written In Python

Truecaller-CLI Command Line Version For Truecaller Written In Python Never Login With A Number Over And Over Or It Will Be Banned Because Program Is S

Sandaru Ashen Fernando 16 Nov 08, 2022
Random scripts and other bits for interacting with the SpaceX Starlink user terminal hardware

starlink-grpc-tools This repository has a handful of tools for interacting with the gRPC service implemented on the Starlink user terminal (AKA "the d

270 Dec 29, 2022
Colab-xterm allows you to open a terminal in a cell

colab-xterm Colab-xterm allows you to open a terminal in a cell. Usage Install package and load the extension !pip install git+https://github.com/popc

InfuseAI 194 Dec 29, 2022
Wik is use to get information about anything on the shell using Wikipedia.

WIK wik is a tool to view wikipedia pages from your terminal. It also let you search for any wikipedia up to date article on one query from your termi

Yash Singh 340 Dec 18, 2022
Ros command - Unifying the ROS command line tools

Unifying the ROS command line tools One impairment to ROS 2 adoption is that all

37 Dec 15, 2022
A simple CLI application helps you to find giant files that are eating up your system storage

Large file finder Sometimes it's very hard to find if some giant files are eating up your system storage. We might need to hunt those down. This simpl

Rahul Baruri 5 Nov 18, 2022
A simple command-line tracert implementation in Python 3 using ICMP packets

Traceroute A simple command-line tracert implementation in Python 3 using ICMP packets Details Traceroute is a networking tool designed for tracing th

James 3 Jul 16, 2022
Simple command line tool to train and deploy your machine learning models with AWS SageMaker

metamaker Simple command line tool to train and deploy your machine learning models with AWS SageMaker Features metamaker enables you to: Build a dock

Yasuhiro Yamaguchi 5 Jan 09, 2022
A command line tool (and Python library) for archiving Twitter JSON

A command line tool (and Python library) for archiving Twitter JSON

Documenting the Now 1.3k Dec 28, 2022
Another (unofficial) Qt CLI Installer on multi-platforms

Another Qt installer(aqt) Release: Documentation: Test status: and Coverage: This is a utility alternative to the official graphical Qt installer, for

Hiroshi Miura 528 Jan 02, 2023
Investing library and command-line interface inspired by the Bogleheads philosophy

Lakshmi (Screenshot of the lak command in action) Background This project is inspired by Bogleheads forum. Bogleheads focus on a simple but powerful p

Sarvjeet Singh 108 Dec 26, 2022
Baseline is a cross-platform library and command-line utility that creates file-oriented baselines of your systems.

Baselining, on steroids! Baseline is a cross-platform library and command-line utility that creates file-oriented baselines of your systems. The proje

Nelson 4 Dec 09, 2022
Amazon Scraper: A command-line tool for scraping Amazon product data

Amazon Product Scraper: 2021 Description A command-line tool for scraping Amazon product data to CSV or JSON format(s). Requirements Python 3 pip3 Ins

49 Nov 15, 2021
A terminal client for connecting to hack.chat servers

A terminal client for connecting to hack.chat servers.

V9 2 Sep 21, 2022
pyNPS - A cli Linux and Windows Nopaystation client made with python 3 and wget

Currently, all the work is being done inside the refactoring branch. pyNPS - A cli Linux and Windows Nopaystation client made with python 3 and wget P

Everton Correia 45 Dec 11, 2022
Gamestonk Terminal is an awesome stock and crypto market terminal

Gamestonk Terminal is an awesome stock and crypto market terminal. A FOSS alternative to Bloomberg Terminal.

Gamestonk Terminal 18.6k Jan 03, 2023
Python wrapper and CLI utility to render LaTeX markup and equations as SVG using dvisvgm and svgo.

latex2svg Python wrapper and CLI utility to render LaTeX markup and equations as SVG using dvisvgm and svgo. Based on the original work by Tino Wagner

Matthias C. Hormann 4 Feb 18, 2022