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)

This is an app for creating your own color scheme for Termux!

Termux Terminal Theme Creator [WIP] If you need help on how to use the program, you can either create a GitHub issue or join this temporary Discord se

asxlvm 3 Dec 31, 2022
Python Library and CLI for exporting MySQL databases

expdb Python library and CLI for exporting MySQL databases Installation Pre-requisites MySQL server Python 3.9+ Using git Clone the repository to your

Devansh Singh 1 Nov 29, 2021
A begginer reverse shell tool python.

A begginer tools for hacking. The theme of this repository is to bring some ready-made open-source tools for anyone new to the world of hacking. This

Dio brando 2 Jan 05, 2022
PyDropper - pick colors everywhere

PyDropper - pick colors everywhere Downloads Settings PyDropper is an eyedropper

Herman Brunberg 2 Jan 04, 2022
Phishing-Detective is a command line application for Windows 10 built to detect a phishing site from two url's

Phishing-Detective Phishing-Detective is a command line application for Windows 10 built to detect a phishing site from two url's How it works A simpl

2 Jun 23, 2022
A terminal client for connecting to hack.chat servers

A terminal client for connecting to hack.chat servers.

V9 2 Sep 21, 2022
A simple python script to execute a command when a YubiKey is disconnected

YubiKeyExecute A python script to execute a command when a YubiKey / YubiKeys are disconnected. ‏‏‎ ‎ How to use: 1. Download the latest release and d

6 Mar 12, 2022
Python CLI for accessing CSCI320 PDM Database

p320_14 Python CLI for accessing CSCI320 PDM Database Authors: Aidan Mellin Dan Skigen Jacob Auger Kyle Baptiste Before running the application for th

Aidan Mellin 1 Nov 23, 2021
Tarstats - A simple Python commandline application that collects statistics about tarfiles

A simple Python commandline application that collects statistics about tarfiles.

Kristian Koehntopp 13 Feb 20, 2022
:computer: tmux session manager. built on libtmux

tmuxp, tmux session manager. built on libtmux. We need help! tmuxp is a trusted session manager for tmux. If you could lend your time to helping answe

python utilities for tmux 3.6k Jan 01, 2023
CLI Web-CAT interface for people who use VIM.

CLI Web-CAT CLI Web-CAT interface. Installation git clone https://github.com/phuang1024/cliwebcat cd cliwebcat python setup.py bdist_wheel sdist cd di

Patrick 4 Apr 11, 2022
A Terminal Client for MySQL with AutoCompletion and Syntax Highlighting.

mycli A command line client for MySQL that can do auto-completion and syntax highlighting. HomePage: http://mycli.net Documentation: http://mycli.net/

dbcli 10.7k Jan 07, 2023
stonky is a simple command line dashboard for monitoring stocks.

stonky is a simple command line dashboard for monitoring stocks.

Jessy Williams 228 Dec 14, 2022
CLI para o projeto Compilado (Newsletter e Podcast do Código Fonte TV)

Compilado CLI Automatização de tarefas através de linha de comando para a geração de assets para episódios do Compilado, a newsletter e podcast do can

Gabriel Froes 18 Nov 21, 2022
An anime command-line system information tool written in python.

Animefetch - v0.0.3 An anime command-line system information tool written in python. Description Animefetch is an anime command-line system informatio

Thadeuks 6 Jun 17, 2022
Easily handle day to day CLI operation via Python instead of regular Bash programs.

pz Ever wished to use Python in Bash? Would you choose the Python syntax over sed, awk, ...? Should you exactly know what command would you use in Pyt

CZ.NIC 697 Jan 03, 2023
A minimal ascii-representation of your local weather.

Ascii-Weather A simple, ascii-based weather visualizer for the terminal. The ascii-art updates to match the current weather and conditions. Uses ipinf

Aaron R. 12 Jan 29, 2022
command line tool for frequent nmigen tasks (generate sources, show design)

nmigen-tool command line tool for frequent nmigen tasks (generate sources, show design) Usage: generate verilog: nmigen generate verilog nmigen_librar

Hans Baier 8 Nov 27, 2022
A Simple Python CLI Lockpicking Tool

Cryptex a simple CLI lockpicking tool What can it do: Encode / Decode Hex Encode / Decode Base64 Break Randomly :D Requirements: Python3 Linux as your

Alex Kollar 23 Jul 04, 2022
A dilligent command line tool to publish ads on ebay-kleinanzeigen.de

kleinanzeigen-bot Feedback and high-quality pull requests are highly welcome! About Installation Usage Development Notes License About kleinanzeigen-b

83 Dec 26, 2022