-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support virtual environment #578
Changes from 10 commits
69f08db
66eb069
0f80a51
f9f53e6
9be4dd7
31ef039
131369c
7866c93
d16a4d4
9dde9a8
7bb0d13
ef27d1d
83b5216
9fcdff7
8fe0cec
41a3107
6d47896
6699140
5e3d621
b517aa3
cc96a4b
e9a6c52
c56ec24
99ec542
923feb9
21f08b3
44beb7c
6a20a5f
5d50878
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,3 +31,86 @@ end | |
|
||
# need to be able to get the version before Python is initialized | ||
Py_GetVersion(libpy) = unsafe_string(ccall(Libdl.dlsym(libpy, :Py_GetVersion), Ptr{UInt8}, ())) | ||
|
||
# Fix the environment for running `python`, and setts IO encoding to UTF-8. | ||
# If cmd is the Conda python, then additionally removes all PYTHON* and | ||
# CONDA* environment variables. | ||
function pythonenv(cmd::Cmd) | ||
env = copy(ENV) | ||
if dirname(cmd.exec[1]) == abspath(Conda.PYTHONDIR) | ||
pythonvars = String[] | ||
for var in keys(env) | ||
if startswith(var, "CONDA") || startswith(var, "PYTHON") | ||
push!(pythonvars, var) | ||
end | ||
end | ||
for var in pythonvars | ||
pop!(env, var) | ||
end | ||
end | ||
# set PYTHONIOENCODING when running python executable, so that | ||
# we get UTF-8 encoded text as output (this is not the default on Windows). | ||
env["PYTHONIOENCODING"] = "UTF-8" | ||
setenv(cmd, env) | ||
end | ||
|
||
|
||
function pythonhome_of(pyprogramname::AbstractString) | ||
if Compat.Sys.iswindows() | ||
# PYTHONHOME tells python where to look for both pure python | ||
# and binary modules. When it is set, it replaces both | ||
# `prefix` and `exec_prefix` and we thus need to set it to | ||
# both in case they differ. This is also what the | ||
# documentation recommends. However, they are documented | ||
# to always be the same on Windows, where it causes | ||
# problems if we try to include both. | ||
script = """ | ||
import sys | ||
if hasattr(sys, "base_exec_prefix"): | ||
sys.stdout.write(sys.base_exec_prefix) | ||
else: | ||
sys.stdout.write(sys.exec_prefix) | ||
""" | ||
else | ||
script = """ | ||
import sys | ||
if hasattr(sys, "base_exec_prefix"): | ||
sys.stdout.write(sys.base_prefix) | ||
sys.stdout.write(":") | ||
sys.stdout.write(sys.base_exec_prefix) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like we should be using |
||
else: | ||
sys.stdout.write(sys.prefix) | ||
sys.stdout.write(":") | ||
sys.stdout.write(sys.exec_prefix) | ||
""" | ||
# https://docs.python.org/3/using/cmdline.html#envvar-PYTHONHOME | ||
end | ||
return read(pythonenv(`$pyprogramname -c $script`), String) | ||
end | ||
# To support `venv` standard library (as well as `virtualenv`), we | ||
# need to use `sys.base_prefix` and `sys.base_exec_prefix` here. | ||
# Otherwise, initializing Python in `__init__` below fails with | ||
# unrecoverable error: | ||
# | ||
# Fatal Python error: initfsencoding: unable to load the file system codec | ||
# ModuleNotFoundError: No module named 'encodings' | ||
# | ||
# This is because `venv` does not symlink standard libraries like | ||
# `virtualenv`. For example, `lib/python3.X/encodings` does not | ||
# exist. Rather, `venv` relies on the behavior of Python runtime: | ||
# | ||
# If a file named "pyvenv.cfg" exists one directory above | ||
# sys.executable, sys.prefix and sys.exec_prefix are set to that | ||
# directory and it is also checked for site-packages | ||
# --- https://docs.python.org/3/library/venv.html | ||
# | ||
# Thus, we need point `PYTHONHOME` to `sys.base_prefix` and | ||
# `sys.base_exec_prefix`. If the virtual environment is created by | ||
# `virtualenv`, those `sys.base_*` paths point to the virtual | ||
# environment. Thus, above code supports both use cases. | ||
# | ||
# See also: | ||
# * https://docs.python.org/3/library/venv.html | ||
# * https://docs.python.org/3/library/site.html | ||
# * https://docs.python.org/3/library/sys.html#sys.base_exec_prefix | ||
# * https://github.com/JuliaPy/PyCall.jl/issues/410 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -667,3 +667,4 @@ def try_call(f): | |
end | ||
|
||
include("test_pyfncall.jl") | ||
include("test_venv.jl") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it sufficient to just run
python -E
to ignorePYTHON*
? Why do we need to removeCONDA*
since we are not runningconda
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I guess we don't want to ignore these variables for non-Conda Python.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pythonenv
is just moved frombuild.jl
todepsutils.jl
to make it usable at runtime.