-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathpython.go
More file actions
118 lines (101 loc) · 3.28 KB
/
Copy pathpython.go
File metadata and controls
118 lines (101 loc) · 3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package jumpboot
import (
"bufio"
"fmt"
"os"
"os/exec"
)
// RunPythonReadCombined executes a Python script and returns combined stdout/stderr.
// This is a blocking call that waits for the script to complete.
func (env *PythonEnvironment) RunPythonReadCombined(scriptPath string, args ...string) (string, error) {
args = append([]string{scriptPath}, args...)
cmd := exec.Command(env.PythonPath, args...)
output, err := cmd.CombinedOutput()
if err != nil {
return string(output), err
}
return string(output), nil
}
// RunPythonReadStdout executes a Python script and returns only stdout.
// This is a blocking call that waits for the script to complete.
func (env *PythonEnvironment) RunPythonReadStdout(scriptPath string, args ...string) (string, error) {
// put scriptPath at the front of the args
retv := ""
args = append([]string{scriptPath}, args...)
cmd := exec.Command(env.PythonPath, args...)
stdout, err := cmd.StdoutPipe()
if err != nil {
return "", err
}
defer stdout.Close()
// continue to read the output until there is no more
// or an error occurs
if err := cmd.Start(); err != nil {
return "", err
}
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
retv += scanner.Text() + "\n"
}
return retv, nil
}
// RunPythonScriptFromFile executes a Python script file, printing stderr to stdout.
// This is a blocking call that waits for the script to complete.
func (env *PythonEnvironment) RunPythonScriptFromFile(scriptPath string, args ...string) error {
// put scriptPath at the front of the args
args = append([]string{scriptPath}, args...)
cmd := exec.Command(env.PythonPath, args...)
// Create a pipe for the output of the script
stdoutPipe, err := cmd.StderrPipe()
if err != nil {
return fmt.Errorf("error creating stdout pipe: %v", err)
}
// Start the command
if err := cmd.Start(); err != nil {
return err
}
// Read from the command's stdout
scanner := bufio.NewScanner(stdoutPipe)
for scanner.Scan() {
fmt.Println("Python script output:", scanner.Text())
}
// Wait for the command to finish
if err := cmd.Wait(); err != nil {
return err
}
return nil
}
// BoundRunPythonScriptFromFile executes a Python script with proper signal handling.
// If the parent Go process receives a termination signal, the Python child is killed.
// This is the recommended way to run Python scripts as long-running subprocesses.
func (env *PythonEnvironment) BoundRunPythonScriptFromFile(scriptPath string, args ...string) error {
// Create the command
// put scriptPath at the front of the args
args = append([]string{scriptPath}, args...)
cmd := exec.Command(env.PythonPath, args...)
// Create a pipe for the output of the script
stdoutPipe, err := cmd.StderrPipe()
if err != nil {
return err
}
// Start the command
if err := cmd.Start(); err != nil {
return err
}
// Create a channel to receive signals
signalChan := make(chan os.Signal, 1)
setSignalsForChannel(signalChan)
// Wait for the command to finish or a signal to be received
go func() {
<-signalChan
// Kill the child process when a signal is received
cmd.Process.Kill()
}()
// Read from the command's stdout
scanner := bufio.NewScanner(stdoutPipe)
for scanner.Scan() {
fmt.Println("Python script output:", scanner.Text())
}
// Wait for the command to finish
return waitForExit(cmd)
}