如何在Go中使用Python模块中的变量?

时间:2019-10-16 23:05:09

标签: python go

我正在Go中构建一个工具,该工具需要提供一种方法来解析在Python脚本的全局范围内声明的变量。将来,我也想将其扩展到Node.js。它必须是跨平台的。

基本上,如果有人要使用以下Python代码:

#!/usr/bin/env python

hello = "world"
some_var = "one"
another_var = "two"
var_three = some_func()

我想在我的Golang代码中访问这些变量键和值。对于该函数,我想访问它返回的值。

我当前的想法是使用Golang exec.Command函数运行脚本,并以某种格式(例如JSON)将变量打印到其stdout上,而后者又可以用Golang进行解析。有想法吗?

1 个答案:

答案 0 :(得分:2)

它们具有不同的运行时环境。 Golang无法在Python的运行时中直接访问变量。反之亦然。但是,您可以对其进行编程,以通过标准I / O或环境变量传递变量值。关键是确定信息交换的正确格式。

例如,如果python脚本将参数作为输入并将结果编码为JSON,则输出到stdout。然后,您可以使用适当的参数调用脚本,并将标准输出解码为JSON。

例如:

range.py

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:])

main.go

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)
}

输出全局变量

要将Python中的全局变量作为JSON对象输出:

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()

输出:

{"foo": "foo", "bar": "bar"}

对于此脚本,您可以使用与上一个类似的main():


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)
}

输出:

map[string]interface {}{"bar":"bar", "foo":"foo"}