2013-10-16 19 views
6

Tôi đang viết chương trình Go. Từ chương trình Go này, tôi muốn gọi hàm Python được định nghĩa trong một tệp khác và nhận giá trị trả về của hàm để tôi có thể sử dụng nó trong quá trình xử lý tiếp theo trong chương trình Go của tôi. Tôi đang gặp khó khăn khi nhận lại bất kỳ dữ liệu nào trong chương trình Go của tôi. Dưới đây là một ví dụ tối thiểu là những gì tôi nghĩ sẽ làm việc, nhưng dường như không:Gọi chức năng Python từ Go và nhận giá trị trả về hàm

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 

Nếu tôi gọi go run gofile Tôi nhận được kết quả sau:

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

Một vài lưu ý:

  • Tôi đang sử dụng -c cờ trong invocation Python vì vậy tôi có thể gọi hàm cat_strings trực tiếp. Giả sử cat_strings là một phần của tệp Python đầy đủ các hàm tiện ích được sử dụng bởi các chương trình Python khác, do đó tại sao tôi không có bất kỳ hoạt động kinh doanh if __name__ == __main__ nào.
  • Tôi không muốn sửa đổi tệp Python thành print a + b (thay vì return a + b); xem điểm trước về hàm là một phần của một tập hợp các hàm tiện ích cần được gọi bằng mã Python khác.
  • Chức năng cat_strings là hư cấu và cho mục đích trình diễn; chức năng thực sự là thứ tôi không muốn đơn giản thực hiện lại trong Go. Tôi thực sự quan tâm đến cách tôi có thể gọi một hàm Python từ Go và nhận giá trị trả về.
+0

Tôi có cảm giác rằng việc này không thể thực hiện dễ dàng bằng cách sử dụng 'os/exec'. Tất cả các hàm 'os/exec' chỉ trả về stdout và/hoặc stderr. – Intermernet

+0

Hãy xem https://github.com/sbinet/go-python và http://stackoverflow.com/questions/12443203/writing-a-python-extension-in-go-golang – Intermernet

+0

@Intermernet Tôi nghĩ rằng gọi 'print' trong' python -c 'nhập pythonfile; print pythonfile.cat_strings ("foo", "bar") ''sẽ được in thành stdout. –

Trả lời

8

tôi quản lý để có một số mã làm việc cho điều này bằng cách loại bỏ quote xung quanh lệnh riêng của mình:

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

Và đủ chắc chắn, trong source, bạn có chức năng này (dành cho Windows, ít nhất , tôi không biết nếu mà làm việc cho hệ điều hành khác):

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

vì vậy, mã của bạn được kết thúc đi qua các cuộc gọi dòng lệnh sau:

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

Mà, nếu được kiểm tra, đánh giá thành một chuỗi và không trả về kết quả nào, do đó đầu ra có độ dài 0.

+0

Chỉ cần thử nghiệm trên Linux (Ubuntu) và loại bỏ các báo giá duy nhất hoạt động, do đó, có vẻ là một giải pháp đa nền tảng. –

+4

Rất tuyệt! Vui vẻ giúp đỡ. Mặc dù như được đề xuất khác, nếu bạn sử dụng nhiều, bạn có thể sử dụng các ràng buộc CPython API tốt hơn hoặc sử dụng giao diện mạng để giao tiếp giữa Python và Go. – val

Các vấn đề liên quan