Call Python function from Go and get function return value

I am writing a Go program. From this Go program, I would like to name the Python function defined in another file and get the return value of the function so that I can use it in subsequent processing in my Go program. However, I am having problems returning any returned data to my Go program. Below is a minimal example of what I thought would work, but apparently not:

gofile.go

package main import "os/exec" import "fmt" func main() { fmt.Println("here we go...") program := "python" arg0 := "-c" arg1 := fmt.Sprintf("'import pythonfile; print pythonfile.cat_strings(\"%s\", \"%s\")'", "foo", "bar") cmd := exec.Command(program, arg0, arg1) fmt.Println("command args:", cmd.Args) out, err := cmd.CombinedOutput() if err != nil { fmt.Println("Concatenation failed with error:", err.Error()) return } fmt.Println("concatentation length: ", len(out)) fmt.Println("concatenation: ", string(out)) fmt.Println("...done") } 

pythonfile.py

 def cat_strings(a, b): return a + b 

If I call go run gofile , I get the following output:

 here we go... command args: [python -c 'import pythonfile; print pythonfile.cat_strings("foo", "bar")'] concatentation length: 0 concatenation: ...done 

A few notes:

  • I use the -c flag in a Python call, so I can directly call the cat_strings function. Suppose cat_strings is part of a Python file full of utility functions that are used by other Python programs, so I don't have a business if __name__ == __main__ .
  • I do not want to modify the Python file until print a + b (instead of return a + b ); see the previous point that a function is part of a set of utility functions that must be called by other Python code.
  • The cat_strings function is fictitious for demonstration purposes; the real function is that I don't want to just override in Go. I'm really curious how I can call a Python function from Go and get the return value.
+6
python go
source share
1 answer

I managed to get some working code for this by simply deleting the quote around the command itself:

 package main import "fmt" import "os/exec" func main() { cmd := exec.Command("python", "-c", "import pythonfile; print pythonfile.cat_strings('foo', 'bar')") fmt.Println(cmd.Args) out, err := cmd.CombinedOutput() if err != nil { fmt.Println(err); } fmt.Println(string(out)) } 

And of course, in the source you have this function (for Windows, at least I don't know if this works for other OSs):

 // EscapeArg rewrites command line argument s as prescribed // in http://msdn.microsoft.com/en-us/library/ms880421. // This function returns "" (2 double quotes) if s is empty. // Alternatively, these transformations are done: // - every back slash (\) is doubled, but only if immediately // followed by double quote ("); // - every double quote (") is escaped by back slash (\); // - finally, s is wrapped with double quotes (arg -> "arg"), // but only if there is space or tab inside s. func EscapeArg(s string) string { ... 

So, your code ends with passing the following command line call:

 $ python -c "'import pythonfile; print pythonfile.cat_strings(\\"foo\\", \\"bar\\")'" 

What, if checked, evaluates the string and returns nothing, therefore, output of length 0.

+8
source share

All Articles