Reputation: 129
I am building a tool in Go which needs to provide a way to resolve variables declared in the global scope of Python scripts. In the future I would like to extend this to Node.js as well. It needs to be cross-platform.
Basically, if someone were to have the following Python code:
#!/usr/bin/env python
hello = "world"
some_var = "one"
another_var = "two"
var_three = some_func()
I would like to have access to these variable keys and values in my Golang code. In case of the function, I would like to have access to the value it returns.
My current idea is to run the script with the Golang exec.Command
function and have the variables printed to its stdout in some format (e.g. JSON), which in turn can be parsed with Golang. Thoughts?
Upvotes: 0
Views: 983
Reputation: 7873
They are of different runtime environments. Golang cannot directly access variables in Python's runtime. Vica versa. You can, however, program them to pass on variable values through standard I/O or environment variables. The key is to determine the proper format for information exchanges.
For example, if the python script takes arguments as input and print the result, encoded as JSON, to the stdout. Then you can call the script with proper arguments, and decode the stdout as JSON.
Such as:
import json
import sys
def toNum(str):
return int(str)
def main(argv):
# Basically called range() with all the arguments from script call
print(json.dumps(list(range(*map(toNum, argv)))))
if __name__ == '__main__':
main(sys.argv[1:])
package main
import (
"encoding/json"
"fmt"
"log"
"os/exec"
)
func pythonRange(start, stop, step int) (c []byte, err error) {
return exec.Command(
"python3",
"./range.py",
fmt.Sprintf("%d", start),
fmt.Sprintf("%d", stop),
fmt.Sprintf("%d", step),
).Output()
}
func main() {
var arr []int
// get the output of the python script
result, err := pythonRange(1, 10, 1)
if err != nil {
log.Fatal(err)
}
// decode the stdout of the python script
// as a json array of integer
err = json.Unmarshal(result, &arr)
if err != nil {
log.Fatal(err)
}
// show the result with log.Printf
log.Printf("%#v", arr)
}
To output global variables in Python as JSON object:
import json
def dump_globals():
# Basically called range() with all the arguments from script call
vars = dict()
for (key, value) in globals().items():
if key.startswith("__") and key.endswith("__"):
continue # skip __varname__ variables
try:
json.dumps(value) # test if value is json serializable
vars[key] = value
except:
continue
print(json.dumps(vars))
foo = "foo"
bar = "bar"
dump_globals()
Output:
{"foo": "foo", "bar": "bar"}
You can use a main() similar to the last one for this script:
import (
"encoding/json"
"fmt"
"log"
"os/exec"
)
func pythonGetVars() (c []byte, err error) {
return exec.Command(
"python3",
"./dump_globals.py",
).Output()
}
func main() {
var vars map[string]interface{}
// get the output of the python script
result, err := pythonGetVars()
if err != nil {
log.Fatal(err)
}
// decode the json object
err = json.Unmarshal(result, &vars)
if err != nil {
log.Fatal(err)
}
// show the result with log.Printf
fmt.Printf("%#v", vars)
}
Output:
map[string]interface {}{"bar":"bar", "foo":"foo"}
Upvotes: 2