CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-python-shell

Run Python scripts from Node.js with efficient inter-process communication through stdio

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

interactive-shell.mddocs/

Interactive Shell

Interactive Python shell class for persistent processes with real-time data exchange through events and streams. This enables bidirectional communication with long-running Python processes.

Capabilities

PythonShell Constructor

Creates an instance of PythonShell and starts the Python process.

/**
 * Creates an interactive Python shell and starts the Python process
 * @param scriptPath - The path of the script to execute (cannot be empty)
 * @param options - The execution options
 * @param stdoutSplitter - Optional custom stdout splitter (defaults to NewlineTransformer)
 * @param stderrSplitter - Optional custom stderr splitter (defaults to NewlineTransformer)
 */
constructor(scriptPath: string, options?: Options, stdoutSplitter: Transform = null, stderrSplitter: Transform = null);

Usage Examples:

import { PythonShell } from "python-shell";
import { Transform } from "stream"; // For custom splitters

// Basic interactive shell
const pyshell = new PythonShell('interactive_script.py');

// With options
const pyshell = new PythonShell('data_processor.py', {
  mode: 'json',
  pythonPath: 'python3',
  scriptPath: './scripts',
  args: ['--interactive'],
  pythonOptions: ['-u']
});

// With custom stream splitters
import { Transform } from 'stream';
const customSplitter = new Transform({
  transform(chunk, encoding, callback) {
    // Custom chunk processing
    callback(null, chunk);
  }
});
const pyshell = new PythonShell('script.py', {}, customSplitter);

Send Message

Sends a message to the Python script via stdin.

/**
 * Sends a message to the Python shell through stdin
 * Data is formatted according to the selected mode or custom formatter
 * @param message - The message to send (string or object)
 * @returns The same instance for chaining calls
 */
send(message: string | Object): PythonShell;

Usage Examples:

// Send text messages
pyshell.send('process this data');
pyshell.send('another message');

// Send structured data in JSON mode
const pyshell = new PythonShell('json_processor.py', { mode: 'json' });
pyshell.send({ command: 'process', data: [1, 2, 3] });
pyshell.send({ command: 'save', filename: 'output.json' });

// Method chaining
pyshell
  .send('first message')
  .send('second message')
  .send('third message');

End Process

Closes the stdin stream and allows the Python process to exit.

/**
 * Closes the stdin stream, allowing the Python script to finish and exit
 * The callback is invoked when the process terminates
 * @param callback - Function called when process terminates
 * @returns The same instance for chaining calls
 */
end(callback: (err: PythonShellError, exitCode: number, exitSignal: string) => any): PythonShell;

Usage Examples:

// Basic process termination
pyshell.end((err, code, signal) => {
  if (err) {
    console.error('Process failed:', err.message);
    console.error('Exit code:', err.exitCode);
    console.error('Traceback:', err.traceback);
  } else {
    console.log('Process completed successfully');
    console.log('Exit code:', code);
  }
});

// With promise wrapper
function endShell(shell) {
  return new Promise((resolve, reject) => {
    shell.end((err, code, signal) => {
      if (err) reject(err);
      else resolve({ code, signal });
    });
  });
}

try {
  const result = await endShell(pyshell);
  console.log('Finished with code:', result.code);
} catch (error) {
  console.error('Error:', error.message);
}

Kill Process

Terminates the Python process with a signal.

/**
 * Sends a kill signal to the process
 * @param signal - Kill signal (defaults to SIGTERM)
 * @returns The same instance for chaining calls
 */
kill(signal?: NodeJS.Signals): PythonShell;

/**
 * Alias for kill method (deprecated)
 * @deprecated Use kill() instead
 */
terminate(signal?: NodeJS.Signals): PythonShell;

Usage Examples:

// Graceful termination
pyshell.kill(); // Uses SIGTERM by default

// Force kill
pyshell.kill('SIGKILL');

// With timeout fallback
const killTimeout = setTimeout(() => {
  console.log('Force killing unresponsive process');
  pyshell.kill('SIGKILL');
}, 5000);

pyshell.kill('SIGTERM');
pyshell.on('close', () => {
  clearTimeout(killTimeout);
});

Event Handling

PythonShell extends EventEmitter and emits several events:

Message Event

Emitted for each parsed chunk from stdout (not in binary mode).

on(event: 'message', listener: (parsedChunk: any) => void): this;

Usage Examples:

// Text mode messages
const pyshell = new PythonShell('script.py', { mode: 'text' });
pyshell.on('message', (message) => {
  console.log('Received text:', message); // string
});

// JSON mode messages
const jsonShell = new PythonShell('json_script.py', { mode: 'json' });
jsonShell.on('message', (data) => {
  console.log('Received object:', data); // parsed JSON object
});

Stderr Event

Emitted for each parsed chunk from stderr (not in binary mode).

on(event: 'stderr', listener: (parsedChunk: any) => void): this;

Usage Examples:

pyshell.on('stderr', (stderr) => {
  console.log('Python stderr:', stderr);
  // Handle warnings, debug info, or errors
});

Close Event

Emitted when the process terminates.

on(event: 'close', listener: () => void): this;

Error Event

Emitted when the process could not be spawned, killed, or communication failed.

on(event: 'error', listener: (error: NodeJS.ErrnoException) => void): this;

Python Error Event

Emitted when the process terminates with a non-zero exit code.

on(event: 'pythonError', listener: (error: PythonShellError) => void): this;

Complete Event Handling Example:

import { PythonShell } from "python-shell";

const pyshell = new PythonShell('interactive_app.py', {
  mode: 'json',
  pythonOptions: ['-u']
});

// Handle successful messages
pyshell.on('message', (data) => {
  console.log('Received:', data);
  
  if (data.type === 'request_input') {
    pyshell.send({ type: 'user_input', value: 'Hello Python!' });
  }
});

// Handle stderr (warnings, debug info)
pyshell.on('stderr', (stderr) => {
  console.warn('Python stderr:', stderr);
});

// Handle Python-specific errors
pyshell.on('pythonError', (error) => {
  console.error('Python error:', error.message);
  console.error('Traceback:', error.traceback);
  console.error('Exit code:', error.exitCode);
});

// Handle system errors
pyshell.on('error', (error) => {
  console.error('System error:', error.message);
  console.error('Error code:', error.code);
});

// Handle process completion
pyshell.on('close', () => {
  console.log('Python process closed');
});

// Start communication
pyshell.send({ type: 'init', config: { debug: true } });

Instance Properties

The PythonShell instance exposes several properties for monitoring and control:

readonly scriptPath: string;      // Path of the script being executed
readonly command: string[];       // Full command arguments passed to Python
readonly mode: string;           // Data exchange mode (text/json/binary)
readonly terminated: boolean;     // Whether the process has exited
readonly childProcess: ChildProcess; // Underlying child process
readonly stdin: Writable;        // Python stdin stream
readonly stdout: Readable;       // Python stdout stream  
readonly stderr: Readable;       // Python stderr stream
readonly exitCode: number;       // Process exit code (after termination)
readonly exitSignal: string;     // Process exit signal (after termination)

Install with Tessl CLI

npx tessl i tessl/npm-python-shell

docs

configuration.md

index.md

interactive-shell.md

script-execution.md

utilities.md

tile.json