Repository navigation
Pass environment variables to the python interpreter #42
Description
Activity
Yes, when the BEAM starts Erlang uses the process env vars to initialise it's internal env vars store, but further modifications such as
System.put_envonly affect the Erlang data structure. I think the same applies to Python when modifyingsys.environdict. SoSystem.put_envwill not be visible to Python, even if it happens before initialization.I think it would be reasonable for us to pass
System.get_env()when initializing Python and setsys.environto match it exactly. I will have a look at that.(oh and not worth its own issue: how do you pass a pid to send_tagged_objects ? The encoder does not support passing pids in globals)
You should be able to pass pid via globals, the encoder was added together with
send_tagged_objects, however note that those are only available if you install Pythonx from main, not on latest. We have been waiting on feedback regardingsend_tagged_objectsbefore making a release.We decided to not mirror the env vars. Setting
os.environin Python automatically sets the OS process environment variables, so the side-effects can go beyond Python. See #43 (comment). On a sidenote, there is a number of gotchas to make it work on Windows.Instead we documented the current behaviour (#44).
If you want to mirror specific env vars, you can do
Pythonx.evaland setos.environkeys accordingly. A good place to do that may be youdef startin yourApplication, so it happens after Python is initialized, and before you start any processes relying on it.So if I understand correctly, the python environment is set only once when the OTP app boots? There is no way to set env like in
System.cmd("foo", [], env: %{"FOO" => "123"})or something like that for a single interpreter invocation?So if I understand correctly, the python environment is set only once when the OTP app boots?
Pretty much. Technically it is set when you initialize Python interpreter, which is either an explicit call to
Pythonx.uv_init, or on Pythonx application boot if configured viaconfig :pythonx, :uv_init, .... Regardless, the initial Python env vars reflect the env vars given to the Elixir OS process, any furtherSystem.put_envcalls are not accounted for.There is no way to set env like in System.cmd("foo", [], env: %{"FOO" => "123"}) or something like that for a single interpreter invocation?
The interpreter is initialized once and from that point forward the env is global across all
Pythonx.evalcalls, since it's the same OS process. The only way to modify those envs is to directly update Python'sos.environwithinPythonx.eval(and it is persisted into the future evals).Ok thank you, I understand.
Is it a goal for you to support multiple instances of the interpreter in the future? Like defining our own instances with different pyprojects in the app supervision tree and call them with something like
Pythonx.eval(:some_name, "x = 1")?For now I should be able to make an initial call to set the environment variables from a Task in the app boot sequence, or something like that.
Is it a goal for you to support multiple instances of the interpreter in the future?
Not really, see #16 (comment).
For now I should be able to make an initial call to set the environment variables from a Task in the app boot sequence, or something like that.
You can do
Pythonx.evalsynchronously in your applicationdef startthat setsos.environ.Yeah ok that was my idea.
Thank you :)
I would like to know how I can pass environment variables dynamically. It seems that the interpreter inherits environment variables from where the application is booted. But is there a way to add some (from loaded
.envfile inruntime.exs) or remove/overwrite some, to avoid leaking sensitive data or swap an API key for another ?Thank you :)
(oh and not worth its own issue: how do you pass a pid to send_tagged_objects ? The encoder does not support passing pids in globals)