Как сделать переменные из модуля Python доступными в Go? - PullRequest
0 голосов
/ 17 октября 2019

Я создаю инструмент в 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), который в свою очередь может быть проанализирован с Golang. Мысли?

1 Ответ

2 голосов
/ 17 октября 2019

Они имеют разные среды выполнения. Golang не может напрямую обращаться к переменным во время выполнения Python. Vica наоборот. Однако вы можете запрограммировать их на передачу значений переменных через стандартный ввод / вывод или переменные окружения. Ключ должен определить правильный формат для обмена информацией.

Например, если скрипт Python принимает аргументы в качестве входных данных и выводит результат, закодированный как JSON, в стандартный вывод. Затем вы можете вызвать скрипт с правильными аргументами и декодировать стандартный вывод в формате 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"}

Вы можете использовать главную() аналогично предыдущему для этого сценария:


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"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...