2013-10-16 20 views
6

私はGoプログラムを書いています。このGoプログラムから、別のファイルで定義されたPython関数を呼び出して関数の戻り値を受け取って、Goプログラムの後続処理で使用できるようにしたいと思います。私はGoプログラムで返されたデータを取り戻すことができません。以下は、私が仕事だろうと思ったものの最小の例であるが、どうやらない:GoからPython関数を呼び出して関数の戻り値を取得する

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 

私はgo run gofileを呼び出す場合私は次の出力を得ます:

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

いくつかの注意事項:

  • 私が直接機能cat_stringsを呼び出すことができますので、私はPythonの呼び出しで-cフラグを使用しています。 cat_stringsは、他のPythonプログラムで使用されているユーティリティ関数でいっぱいになっているPythonファイルの一部であると仮定して、なぜ私はif __name__ == __main__ビジネスを持っていません。
  • 私はPythonファイルをprint a + breturn a + bではなく)に変更したくありません。関数が他のPythonコードで呼び出し可能でなければならない一連のユーティリティ関数の一部であることについての先の点を参照してください。
  • cat_strings機能は架空のものであり、デモンストレーションの目的で使用されます。実際の関数は、単にGoで再実装したくないものです。私はGoからPython関数を呼び出すことができ、戻り値を得る方法に本当に興味があります。
+0

私はこれが 'os/exec'を使って簡単に行えないと感じています。すべての 'os/exec'関数は、stdoutおよび/またはstderrのみを返します。 – Intermernet

+0

https://github.com/sbinet/go-pythonとhttp://stackoverflow.com/questions/12443203/writing-a-python-extension-in-go-golang – Intermernet

+0

@Intermernet私は私のことを考えました'python -c 'の' print'を呼び出します。pythonfileをインポートします。 print pythonfile.cat_strings( "foo"、 "bar") ''はstdoutに出力されます。 –

答えて

8

私は単純にコマンド自体の周りに引用符を削除することで、このためのいくつかの作業コードを持っているために管理:

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

そして案の定、sourceに、あなたは少なくとも、Windows用(この機能を持っていますそれは他のOSで動作している場合、私は)分からない:

// 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 { ... 

だからあなたのコードは、次のコマンドライン呼び出しを渡して終わるされます

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

テストされた場合、文字列に評価され、何も返さないため、長さ0の出力が返されます。

+0

Linux(Ubuntu)でテストして、一重引用符を削除するだけで、クロスプラットフォームのソリューションと思われます。 –

+4

ニース!お力になれて、嬉しいです。他にも示唆されているように、CPython APIバインディングを使用する方が良いかもしれませんが、ネットワークインタフェースを使ってPythonとGoの間でやりとりしてください。 – val

関連する問題