0
# Interactive Shell
1
2
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.
3
4
## Capabilities
5
6
### PythonShell Constructor
7
8
Creates an instance of PythonShell and starts the Python process.
9
10
```typescript { .api }
11
/**
12
* Creates an interactive Python shell and starts the Python process
13
* @param scriptPath - The path of the script to execute (cannot be empty)
14
* @param options - The execution options
15
* @param stdoutSplitter - Optional custom stdout splitter (defaults to NewlineTransformer)
16
* @param stderrSplitter - Optional custom stderr splitter (defaults to NewlineTransformer)
17
*/
18
constructor(scriptPath: string, options?: Options, stdoutSplitter: Transform = null, stderrSplitter: Transform = null);
19
```
20
21
**Usage Examples:**
22
23
```typescript
24
import { PythonShell } from "python-shell";
25
import { Transform } from "stream"; // For custom splitters
26
27
// Basic interactive shell
28
const pyshell = new PythonShell('interactive_script.py');
29
30
// With options
31
const pyshell = new PythonShell('data_processor.py', {
32
mode: 'json',
33
pythonPath: 'python3',
34
scriptPath: './scripts',
35
args: ['--interactive'],
36
pythonOptions: ['-u']
37
});
38
39
// With custom stream splitters
40
import { Transform } from 'stream';
41
const customSplitter = new Transform({
42
transform(chunk, encoding, callback) {
43
// Custom chunk processing
44
callback(null, chunk);
45
}
46
});
47
const pyshell = new PythonShell('script.py', {}, customSplitter);
48
```
49
50
### Send Message
51
52
Sends a message to the Python script via stdin.
53
54
```typescript { .api }
55
/**
56
* Sends a message to the Python shell through stdin
57
* Data is formatted according to the selected mode or custom formatter
58
* @param message - The message to send (string or object)
59
* @returns The same instance for chaining calls
60
*/
61
send(message: string | Object): PythonShell;
62
```
63
64
**Usage Examples:**
65
66
```typescript
67
// Send text messages
68
pyshell.send('process this data');
69
pyshell.send('another message');
70
71
// Send structured data in JSON mode
72
const pyshell = new PythonShell('json_processor.py', { mode: 'json' });
73
pyshell.send({ command: 'process', data: [1, 2, 3] });
74
pyshell.send({ command: 'save', filename: 'output.json' });
75
76
// Method chaining
77
pyshell
78
.send('first message')
79
.send('second message')
80
.send('third message');
81
```
82
83
### End Process
84
85
Closes the stdin stream and allows the Python process to exit.
86
87
```typescript { .api }
88
/**
89
* Closes the stdin stream, allowing the Python script to finish and exit
90
* The callback is invoked when the process terminates
91
* @param callback - Function called when process terminates
92
* @returns The same instance for chaining calls
93
*/
94
end(callback: (err: PythonShellError, exitCode: number, exitSignal: string) => any): PythonShell;
95
```
96
97
**Usage Examples:**
98
99
```typescript
100
// Basic process termination
101
pyshell.end((err, code, signal) => {
102
if (err) {
103
console.error('Process failed:', err.message);
104
console.error('Exit code:', err.exitCode);
105
console.error('Traceback:', err.traceback);
106
} else {
107
console.log('Process completed successfully');
108
console.log('Exit code:', code);
109
}
110
});
111
112
// With promise wrapper
113
function endShell(shell) {
114
return new Promise((resolve, reject) => {
115
shell.end((err, code, signal) => {
116
if (err) reject(err);
117
else resolve({ code, signal });
118
});
119
});
120
}
121
122
try {
123
const result = await endShell(pyshell);
124
console.log('Finished with code:', result.code);
125
} catch (error) {
126
console.error('Error:', error.message);
127
}
128
```
129
130
### Kill Process
131
132
Terminates the Python process with a signal.
133
134
```typescript { .api }
135
/**
136
* Sends a kill signal to the process
137
* @param signal - Kill signal (defaults to SIGTERM)
138
* @returns The same instance for chaining calls
139
*/
140
kill(signal?: NodeJS.Signals): PythonShell;
141
142
/**
143
* Alias for kill method (deprecated)
144
* @deprecated Use kill() instead
145
*/
146
terminate(signal?: NodeJS.Signals): PythonShell;
147
```
148
149
**Usage Examples:**
150
151
```typescript
152
// Graceful termination
153
pyshell.kill(); // Uses SIGTERM by default
154
155
// Force kill
156
pyshell.kill('SIGKILL');
157
158
// With timeout fallback
159
const killTimeout = setTimeout(() => {
160
console.log('Force killing unresponsive process');
161
pyshell.kill('SIGKILL');
162
}, 5000);
163
164
pyshell.kill('SIGTERM');
165
pyshell.on('close', () => {
166
clearTimeout(killTimeout);
167
});
168
```
169
170
## Event Handling
171
172
PythonShell extends EventEmitter and emits several events:
173
174
### Message Event
175
176
Emitted for each parsed chunk from stdout (not in binary mode).
177
178
```typescript { .api }
179
on(event: 'message', listener: (parsedChunk: any) => void): this;
180
```
181
182
**Usage Examples:**
183
184
```typescript
185
// Text mode messages
186
const pyshell = new PythonShell('script.py', { mode: 'text' });
187
pyshell.on('message', (message) => {
188
console.log('Received text:', message); // string
189
});
190
191
// JSON mode messages
192
const jsonShell = new PythonShell('json_script.py', { mode: 'json' });
193
jsonShell.on('message', (data) => {
194
console.log('Received object:', data); // parsed JSON object
195
});
196
```
197
198
### Stderr Event
199
200
Emitted for each parsed chunk from stderr (not in binary mode).
201
202
```typescript { .api }
203
on(event: 'stderr', listener: (parsedChunk: any) => void): this;
204
```
205
206
**Usage Examples:**
207
208
```typescript
209
pyshell.on('stderr', (stderr) => {
210
console.log('Python stderr:', stderr);
211
// Handle warnings, debug info, or errors
212
});
213
```
214
215
### Close Event
216
217
Emitted when the process terminates.
218
219
```typescript { .api }
220
on(event: 'close', listener: () => void): this;
221
```
222
223
### Error Event
224
225
Emitted when the process could not be spawned, killed, or communication failed.
226
227
```typescript { .api }
228
on(event: 'error', listener: (error: NodeJS.ErrnoException) => void): this;
229
```
230
231
### Python Error Event
232
233
Emitted when the process terminates with a non-zero exit code.
234
235
```typescript { .api }
236
on(event: 'pythonError', listener: (error: PythonShellError) => void): this;
237
```
238
239
**Complete Event Handling Example:**
240
241
```typescript
242
import { PythonShell } from "python-shell";
243
244
const pyshell = new PythonShell('interactive_app.py', {
245
mode: 'json',
246
pythonOptions: ['-u']
247
});
248
249
// Handle successful messages
250
pyshell.on('message', (data) => {
251
console.log('Received:', data);
252
253
if (data.type === 'request_input') {
254
pyshell.send({ type: 'user_input', value: 'Hello Python!' });
255
}
256
});
257
258
// Handle stderr (warnings, debug info)
259
pyshell.on('stderr', (stderr) => {
260
console.warn('Python stderr:', stderr);
261
});
262
263
// Handle Python-specific errors
264
pyshell.on('pythonError', (error) => {
265
console.error('Python error:', error.message);
266
console.error('Traceback:', error.traceback);
267
console.error('Exit code:', error.exitCode);
268
});
269
270
// Handle system errors
271
pyshell.on('error', (error) => {
272
console.error('System error:', error.message);
273
console.error('Error code:', error.code);
274
});
275
276
// Handle process completion
277
pyshell.on('close', () => {
278
console.log('Python process closed');
279
});
280
281
// Start communication
282
pyshell.send({ type: 'init', config: { debug: true } });
283
```
284
285
## Instance Properties
286
287
The PythonShell instance exposes several properties for monitoring and control:
288
289
```typescript { .api }
290
readonly scriptPath: string; // Path of the script being executed
291
readonly command: string[]; // Full command arguments passed to Python
292
readonly mode: string; // Data exchange mode (text/json/binary)
293
readonly terminated: boolean; // Whether the process has exited
294
readonly childProcess: ChildProcess; // Underlying child process
295
readonly stdin: Writable; // Python stdin stream
296
readonly stdout: Readable; // Python stdout stream
297
readonly stderr: Readable; // Python stderr stream
298
readonly exitCode: number; // Process exit code (after termination)
299
readonly exitSignal: string; // Process exit signal (after termination)
300
```