0
# Utilities
1
2
Utility functions for Python environment management, syntax checking, version detection, and stream processing. These functions provide helpful tools for working with Python environments and validating code before execution.
3
4
## Capabilities
5
6
### Syntax Checking
7
8
Validate Python code syntax without executing it, useful for code validation and error prevention.
9
10
### Check Code String Syntax
11
12
Validates Python code syntax from a string without execution.
13
14
```typescript { .api }
15
/**
16
* Checks syntax of Python code string without executing
17
* Creates temporary file for syntax validation
18
* @param code - Python code string to validate
19
* @returns Promise that resolves if syntax is valid, rejects with error details if invalid
20
*/
21
static async checkSyntax(code: string): Promise<void>;
22
```
23
24
**Usage Examples:**
25
26
```typescript
27
import { PythonShell } from "python-shell";
28
29
// Valid syntax
30
try {
31
await PythonShell.checkSyntax('print("Hello, World!")');
32
console.log('Syntax is valid');
33
} catch (error) {
34
console.error('Syntax error:', error.message);
35
}
36
37
// Invalid syntax
38
try {
39
await PythonShell.checkSyntax('print("Missing closing quote');
40
} catch (error) {
41
console.error('Syntax error detected:', error.stderr);
42
// Error contains Python compiler error message
43
}
44
45
// Complex code validation
46
const pythonCode = `
47
import json
48
import sys
49
50
def process_data(data):
51
if not isinstance(data, list):
52
raise ValueError("Data must be a list")
53
return [x * 2 for x in data if x > 0]
54
55
if __name__ == "__main__":
56
data = json.loads(sys.argv[1])
57
result = process_data(data)
58
print(json.dumps(result))
59
`;
60
61
try {
62
await PythonShell.checkSyntax(pythonCode);
63
console.log('Complex code syntax is valid');
64
} catch (error) {
65
console.error('Syntax issues found:', error.stderr);
66
}
67
```
68
69
### Check File Syntax
70
71
Validates Python file syntax without execution.
72
73
```typescript { .api }
74
/**
75
* Checks syntax of Python file without executing
76
* Uses py_compile module for validation
77
* @param filePath - Path to Python file to validate
78
* @returns Promise that resolves if syntax is valid, rejects with error details if invalid
79
*/
80
static async checkSyntaxFile(filePath: string): Promise<void>;
81
```
82
83
**Usage Examples:**
84
85
```typescript
86
import { PythonShell } from "python-shell";
87
import { promises as fs } from 'fs';
88
89
// Check individual file
90
try {
91
await PythonShell.checkSyntaxFile('./scripts/data_processor.py');
92
console.log('File syntax is valid');
93
} catch (error) {
94
console.error('File has syntax errors:', error.stderr);
95
}
96
97
// Batch validate multiple files
98
const scriptFiles = [
99
'./scripts/processor.py',
100
'./scripts/validator.py',
101
'./scripts/exporter.py'
102
];
103
104
const results = await Promise.allSettled(
105
scriptFiles.map(file => PythonShell.checkSyntaxFile(file))
106
);
107
108
results.forEach((result, index) => {
109
if (result.status === 'fulfilled') {
110
console.log(`${scriptFiles[index]}: Valid syntax`);
111
} else {
112
console.error(`${scriptFiles[index]}: Syntax error -`, result.reason.stderr);
113
}
114
});
115
116
// Validate before execution
117
async function safeExecute(scriptPath: string, options?: Options) {
118
try {
119
await PythonShell.checkSyntaxFile(scriptPath);
120
return await PythonShell.run(scriptPath, options);
121
} catch (syntaxError) {
122
throw new Error(`Cannot execute ${scriptPath}: ${syntaxError.stderr}`);
123
}
124
}
125
```
126
127
### Python Version Detection
128
129
Get information about Python installations and versions.
130
131
### Get Python Version (Async)
132
133
Asynchronously gets Python version information.
134
135
```typescript { .api }
136
/**
137
* Gets Python version information asynchronously
138
* @param pythonPath - Optional path to specific Python executable
139
* @returns Promise resolving to object with stdout and stderr from version command
140
*/
141
static getVersion(pythonPath?: string): Promise<{stdout: string, stderr: string}>;
142
```
143
144
**Usage Examples:**
145
146
```typescript
147
import { PythonShell } from "python-shell";
148
149
// Get default Python version
150
try {
151
const version = await PythonShell.getVersion();
152
console.log('Python version:', version.stdout.trim());
153
// Output: "Python 3.9.7"
154
} catch (error) {
155
console.error('Python not found or error getting version:', error.message);
156
}
157
158
// Check specific Python installation
159
try {
160
const version = await PythonShell.getVersion('/usr/bin/python3.10');
161
console.log('Python 3.10 version:', version.stdout.trim());
162
} catch (error) {
163
console.error('Python 3.10 not found:', error.message);
164
}
165
166
// Check multiple Python versions
167
const pythonPaths = ['python', 'python3', 'python3.9', 'python3.10'];
168
const versionChecks = pythonPaths.map(async (path) => {
169
try {
170
const version = await PythonShell.getVersion(path);
171
return { path, version: version.stdout.trim(), available: true };
172
} catch (error) {
173
return { path, error: error.message, available: false };
174
}
175
});
176
177
const results = await Promise.all(versionChecks);
178
results.forEach(result => {
179
if (result.available) {
180
console.log(`${result.path}: ${result.version}`);
181
} else {
182
console.log(`${result.path}: Not available - ${result.error}`);
183
}
184
});
185
```
186
187
### Get Python Version (Sync)
188
189
Synchronously gets Python version information.
190
191
```typescript { .api }
192
/**
193
* Gets Python version information synchronously
194
* @param pythonPath - Optional path to specific Python executable
195
* @returns Python version string
196
*/
197
static getVersionSync(pythonPath?: string): string;
198
```
199
200
**Usage Examples:**
201
202
```typescript
203
import { PythonShell } from "python-shell";
204
205
// Get default Python version synchronously
206
try {
207
const version = PythonShell.getVersionSync();
208
console.log('Python version:', version.trim());
209
} catch (error) {
210
console.error('Error getting Python version:', error.message);
211
}
212
213
// Check specific Python executable
214
try {
215
const version = PythonShell.getVersionSync('./venv/bin/python');
216
console.log('Virtual environment Python:', version.trim());
217
} catch (error) {
218
console.error('Virtual environment Python not found');
219
}
220
221
// Version comparison utility
222
function comparePythonVersions() {
223
try {
224
const systemVersion = PythonShell.getVersionSync('python');
225
const python3Version = PythonShell.getVersionSync('python3');
226
227
console.log('System Python:', systemVersion.trim());
228
console.log('Python3:', python3Version.trim());
229
230
// Extract version numbers for comparison
231
const systemMatch = systemVersion.match(/Python (\d+\.\d+\.\d+)/);
232
const python3Match = python3Version.match(/Python (\d+\.\d+\.\d+)/);
233
234
if (systemMatch && python3Match) {
235
console.log('System version number:', systemMatch[1]);
236
console.log('Python3 version number:', python3Match[1]);
237
}
238
} catch (error) {
239
console.error('Error comparing versions:', error.message);
240
}
241
}
242
```
243
244
### Get Python Path
245
246
Gets the currently configured Python executable path.
247
248
```typescript { .api }
249
/**
250
* Gets the current Python path configuration
251
* Returns either defaultOptions.pythonPath or defaultPythonPath
252
* @returns Current Python executable path
253
*/
254
static getPythonPath(): string;
255
```
256
257
**Usage Examples:**
258
259
```typescript
260
import { PythonShell } from "python-shell";
261
262
// Get current Python path
263
const currentPath = PythonShell.getPythonPath();
264
console.log('Current Python path:', currentPath);
265
// Default: "python3" on Unix, "python" on Windows
266
267
// After setting custom default
268
PythonShell.defaultOptions = { pythonPath: '/usr/bin/python3.9' };
269
const customPath = PythonShell.getPythonPath();
270
console.log('Custom Python path:', customPath); // "/usr/bin/python3.9"
271
272
// Utility to validate current Python setup
273
async function validatePythonSetup() {
274
const pythonPath = PythonShell.getPythonPath();
275
console.log('Using Python executable:', pythonPath);
276
277
try {
278
const version = await PythonShell.getVersion(pythonPath);
279
console.log('Version:', version.stdout.trim());
280
281
// Test basic functionality
282
await PythonShell.checkSyntax('print("Hello")');
283
console.log('Python setup is working correctly');
284
} catch (error) {
285
console.error('Python setup has issues:', error.message);
286
}
287
}
288
```
289
290
### Stream Processing Utilities
291
292
Utility class for processing streams with custom delimiters.
293
294
### NewlineTransformer
295
296
Stream transformer that splits data into chunks separated by newlines.
297
298
```typescript { .api }
299
/**
300
* Stream transformer for splitting data by newlines
301
* Used internally as default stdout/stderr splitter
302
*/
303
class NewlineTransformer extends Transform {
304
/**
305
* Transform stream chunks, splitting by newlines
306
* @param chunk - Input data chunk
307
* @param encoding - Character encoding
308
* @param callback - Completion callback
309
*/
310
_transform(chunk: any, encoding: string, callback: TransformCallback): void;
311
312
/**
313
* Flush remaining data when stream ends
314
* @param done - Completion callback
315
*/
316
_flush(done: TransformCallback): void;
317
}
318
```
319
320
**Usage Examples:**
321
322
```typescript
323
import { PythonShell, NewlineTransformer } from "python-shell";
324
import { Transform } from 'stream';
325
326
// Using NewlineTransformer for custom streams
327
const customPipe = someReadableStream;
328
const newlineTransformer = new NewlineTransformer();
329
330
customPipe
331
.pipe(newlineTransformer)
332
.on('data', (line) => {
333
console.log('Received line:', line.toString());
334
});
335
336
// Custom splitter for special delimiters
337
class CustomSplitter extends Transform {
338
private buffer = '';
339
340
_transform(chunk: any, encoding: string, callback: TransformCallback) {
341
this.buffer += chunk.toString();
342
const parts = this.buffer.split('||'); // Custom delimiter
343
this.buffer = parts.pop() || '';
344
345
parts.forEach(part => this.push(part));
346
callback();
347
}
348
349
_flush(callback: TransformCallback) {
350
if (this.buffer) this.push(this.buffer);
351
callback();
352
}
353
}
354
355
// Use custom splitter with PythonShell
356
const customSplitter = new CustomSplitter();
357
const pyshell = new PythonShell('script.py', {}, customSplitter);
358
359
// Advanced stream processing with multiple custom pipes
360
const options = {
361
stdio: ['pipe', 'pipe', 'pipe', 'pipe'] // stdin, stdout, stderr, custom
362
};
363
364
const pyshell = new PythonShell('advanced_script.py', options);
365
const customStream = pyshell.childProcess.stdio[3];
366
367
if (customStream) {
368
customStream
369
.pipe(new NewlineTransformer())
370
.on('data', (customData) => {
371
console.log('Custom stream data:', customData.toString());
372
});
373
}
374
```
375
376
### Environment Validation Utility
377
378
Combined utility function for comprehensive Python environment validation:
379
380
```typescript
381
// Example comprehensive validation function
382
async function validatePythonEnvironment(options?: Options) {
383
const pythonPath = options?.pythonPath || PythonShell.getPythonPath();
384
385
console.log('Validating Python environment...');
386
console.log('Python path:', pythonPath);
387
388
try {
389
// Check if Python is accessible
390
const version = await PythonShell.getVersion(pythonPath);
391
console.log('✓ Python version:', version.stdout.trim());
392
393
// Test syntax checking
394
await PythonShell.checkSyntax('import sys; print("Hello")');
395
console.log('✓ Syntax checking works');
396
397
// Test basic execution
398
const result = await PythonShell.runString('print("test")', { pythonPath });
399
console.log('✓ Basic execution works:', result);
400
401
// Test with provided options
402
if (options?.pythonOptions) {
403
const testResult = await PythonShell.runString('print("options test")', options);
404
console.log('✓ Custom options work:', testResult);
405
}
406
407
console.log('✓ Python environment validation complete');
408
return true;
409
410
} catch (error) {
411
console.error('✗ Python environment validation failed:', error.message);
412
return false;
413
}
414
}
415
```