Goroutine calls Python but deadlocks #49
Description
Describe what happened:
Does the project support Goroutine?
Recently, I encountered the following problems in the network programming project (simplified version):
- directory structure:
.
├── go.mod
├── go.sum
├── hello
│ ├── model
│ │ └── resnet18.pth
│ └── test.py
├── main.go
└── test
- target
test.py
file :
import torch
from torchvision import models
def Test(m):
print("Call test function")
model = models.resnet18(pretrained=True)
if m == "save":
torch.save(model, "./hello/model/resnet18.pth")
return "model saved."
else:
return torch.load("./hello/model/resnet18.pth")
main.go
:
import (
"fmt"
"github.com/datadog/go-python3"
"os"
)
func init() {
python3.Py_Initialize()
if !python3.Py_IsInitialized() {
fmt.Println("Error initializing the python interpreter")
os.Exit(1)
}
}
func main() {
flagChan := make(chan bool , 1)
testModule := ImportModule("./hello", "test")
Test := testModule.GetAttrString("Test")
args := python3.PyTuple_New(1)
input := python3.PyUnicode_FromString("save")
python3.PyTuple_SetItem(args, 0, input)
res := Test.Call(args, python3.Py_None)
repr, _ := pythonRepr(res)
fmt.Println("[Main FUNC] res =", repr)
go func() {
fmt.Println("goroutine start...")
args := python3.PyTuple_New(1)
defer args.DecRef()
input := python3.PyUnicode_FromString("load")
python3.PyTuple_SetItem(args, 0, input)
res := Test.Call(args, python3.Py_None)
repr, _ := pythonRepr(res)
fmt.Println("[Goroutine FUNC] res =", repr)
fmt.Println("goroutine over")
flagChan <- true
}()
<- flagChan
args.DecRef()
Test.DecRef()
testModule.DecRef()
python3.Py_Finalize()
fmt.Println("main routine over")
select {}
}
func ImportModule(dir, name string) *python3.PyObject {
sysModule := python3.PyImport_ImportModule("sys") // import sys
defer sysModule.DecRef()
path := sysModule.GetAttrString("path") // path = sys.path
defer path.DecRef()
dirObject := python3.PyUnicode_FromString(dir)
defer dirObject.DecRef()
python3.PyList_Insert(path, 0, dirObject) // path.insert(0, dir)
return python3.PyImport_ImportModule(name) // return __import__(name)
}
func pythonRepr(o *python3.PyObject) (string, error) {
if o == nil {
return "", fmt.Errorf("object is nil")
}
s := o.Repr()
if s == nil {
python3.PyErr_Clear()
return "", fmt.Errorf("failed to call Repr object method")
}
defer s.DecRef()
return python3.PyUnicode_AsUTF8(s), nil
}
When I run it, sometimes it works perfectly, but sometimes it blocks python code:
Call test function
[Main FUNC] res = 'model saved.'
goroutine start...
Call test function
(It's always blocked here...)
Describe what you expected:
Call test function
[Main FUNC] res = 'model saved.'
goroutine start...
Call test function
[Goroutine FUNC] res = ResNet(....)
goroutine over
main routine over
I don't know if this is a problem with multiple goroutine resource preemption or not supporting multithreading, or maybe it's a problem with my go-python3 code.
Because I was writing a network communication project, I had to have multiple goroutine receive and send data (Model) enabled on the same node, and the entire python3 environment remained running until the node was shut down. I'm limited in what I can do, so I'd appreciate it if you could take a look