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 Tempmail Tool for Terminal and Termux.

A Tempmail Tool for Terminal and Termux.

MAO-COMMUNITY 8 Oct 19, 2022
Python implementation of SSH file transfer across servers.

SSH Transfer Python implementation of SSH file transfer across servers. Requirements paramiko=2.7.2 Usage Config Preparation Configure some informatio

Zhe Kong 1 Nov 23, 2021
CLI tool to build, test, debug, and deploy Serverless applications using AWS SAM

AWS SAM The AWS Serverless Application Model (SAM) is an open-source framework for building serverless applications. It provides shorthand syntax to e

Amazon Web Services 6.2k Jan 08, 2023
Bad Apple printed out on the console with Python!

Bad Apple printed out on the console with Python!

CalvinLoke 186 Dec 01, 2022
Free and Open-Source Command Line tool for Text Replacement

Sniplet Free and Open Source Text Replacement Tool Description: Sniplet is a work in progress CLI tool which can do text replacement globally in Linux

Veeraraghavan Narasimhan 13 Nov 28, 2022
CLI client for FerrisChat

A CLI Client for @FerrisChat using FerrisWheel

FerrisChat 2 Apr 01, 2022
GitFun - A Simplified Automated CLI tool for GIT😃

GitFun A Simplified Automated CLI tool for GIT, It's for Lazy Developers and Newbies 😜 Table of contents GitFun Installation Usage Development Contri

Astaqc 8 Feb 22, 2022
Todo - You could use terminal to set your todo

Python Tutorial You can learn how to build a terminal application(CLI applicatio

29 Jun 29, 2022
The WalletsNet CLI helps you connect to WalletsNet

WalletsNet CLI The WalletsNet CLI helps you connect to WalletsNet. With the CLI, you can: Trigger webhook events or resend events for easy testing Tai

WalletsClub 8 Dec 22, 2021
Stephen's Obsessive Note-Storage Engine.

Latest Release · PyPi Package · Issues · Changelog · License # Get Sonse and tell it where your notes are... $ pip install sonse $ export SONSE="$HOME

Stephen Malone 23 Jun 10, 2022
Display Images in your terminal with python

A python library to display images in the terminal

Pranav Baburaj 57 Dec 30, 2022
Command line client for Audience Insights

Dynamics 365 Audience Insights CLI The AuI CLI is a command line tool for Dynamics 365 Audience Insights. It is based on the customerinsights Python l

Microsoft 8 Jan 09, 2023
Shellmon is a tool used to create and control a webshell remotely, created using the Python3

An Simple PHP Webshell Manager Description Shellmon is a tool used to create and control a webshell remotely, created using the Python3 programming la

22XploiterCrew 12 Dec 30, 2022
⚙ 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:

Serum 16 Sep 25, 2022
Terminal Colored Text for Python

Terminal Colored Text for Python

R3CKhi-**75 3 Sep 10, 2022
Joji convert a text to corresponding emoji if emoji is available

Joji Joji convert a text to corresponding emoji if emoji is available How it Works ? 1. There is a json file with emoji names as keys and correspondin

Gopikrishnan Sasikumar 28 Nov 26, 2022
CLI program that allows you to change your Alacritty config with one command without editing the config file.

Pycritty Change your alacritty config on the fly! Installation: pip install pycritty By default, only the program itself will be installed, but you ca

Antonio Sarosi 184 Jan 07, 2023
Command line tool for interacting and testing warehouse components

Warehouse debug CLI Example usage for Zumo debugging See all messages queued and handled. Enable by compiling the zumo-controller with -DDEBUG_MODE_EN

1 Jan 03, 2022
A linux-like remote terminal for Micropython

A linux-like remote terminal for Micropython

Christian Köver - Draxl 2 Nov 14, 2021
Urial (URI Addition tooL) intelligently updates URIs stored in Finder comments of macOS files

Urial Urial (URI addition tool) is a simple but intelligent command-line tool to add or replace URIs found inside macOS Finder comments. Table of cont

Mike Hucka 3 Sep 14, 2022