sbinet / go-python

naive go bindings to the CPython2 C-API
Other
1.53k stars 138 forks source link

Question: how to set the embedded Python to virtualenv Python ? #71

Closed sindbach closed 6 years ago

sindbach commented 6 years ago

Hi, I'm trying to write a Go executable that is able to pick up whichever Python version (hence libraries) it's running on. For example, in macOS the default system Python is 2.7.14, but could be executed within Python 3.6.5 virtualenv. As you know, working with virtualenv it's quite nice too, because the libraries installed within the env won't have to be globally installed.

I have tried to prefix the PYTHON_HOME env variable with the VIRTUAL_ENV (Python bin) before python.Initialize(). However this seems to result in still picking the system Python 2.7.14. I can see the PATH env variable started with the correct VIRTUAL_ENV path, but the embedded Python once again is still picking up the system Python.

One of the suggested workarounds on StackOverflow: 7492855 with (Python C API) was to set the program name via Py_SetProgramName. Although I don't seem to be able to find this function on go-python.

Anything suggestions ? or, perhaps I'm missing something quite obvious.

Thanks and regards,
Wan.

sbinet commented 6 years ago

72 exposes Py_SetProgramName and Py_GetProgramName.

could you check this fixes your issue? (please reopen if that's not the case.)

sindbach commented 6 years ago

Hi @sbinet , Thanks for the quick patch and reply.

Unfortunately, this doesn't solve the problem (btw, I can't reopen an issue if it's closed by the repo collaborator).

This is the code that I'm using to test:

func init() {
    const py = "/path/venv3/bin/python3"
    python.Py_SetProgramName(py)
    python.Initialize()
    sys := python.PySys_GetObject("version")
    fmt.Println(python.PyString_AsString(sys))
    prefix := python.PySys_GetObject("prefix")
    fmt.Println(python.PyString_AsString(prefix))
}
func main() {
}

For example, if the system Python is 2.7.14. Execute virtualenv -p /path/python3 venv3 to create virtual env with Python3. Once the virtualenv is activated, executing the compiled Go above still returns Python 2.7.14. It should have printed out the correct Python3 version however.

The method above is also what's suggested on docs.python.org/3: Very High Level Embedding.

The only other possibility is Py_SetPythonHome, but I'm not sure whether that will work either.

Any other thoughts or advice ? Thanks!

sbinet commented 6 years ago

I can add the API for PythonHome.

but I am quite doubtful this will help: go-python is compiled and linked against a specific CPython API, namely CPython-2. I'd be surprised compiling against some random CPython v2.x and then running inside a venv with CPython-3 would reliably work.

sindbach commented 6 years ago

go-python is compiled and linked against a specific CPython API, namely CPython-2.

Hi, Again, thanks for the quick patch and also the reply. You're right, it's linked against specific version of CPython.

Is there a plan on updating the project to be linked against CPython-3 to support Python3 ? With the hope to just move to Python3 support only.

Thanks!

sbinet commented 6 years ago

yes, there's a plan. and there even used to be a PR: https://github.com/sbinet/go-python/pull/66

I think I'll migrate this repo over to the go-python organization as, say cpy2 and start working on a separate repo, say cpy3, to add CPython-3 support.

(ultimately, the goal is to have a cpy2 or cpy3 low-level package that closely follows the CPython C-API, and a high-level py package which would present a much more Go-idiomatic API.)

sindbach commented 6 years ago

Thanks @sbinet