Cannot read environment variable set with PowerShell with os.environ.get - python

A bit of a random problem here. I set an environment variable using PowerShell like this:
$env:GOOGLE_ELEVATION_API="the_api-key"
Then in python I attempt to read it with this simple script:
from os import environ
key = environ.get("GOOGLE_ELEVATION_API")
This returns None. If I query my environment variables in PowerShell it is there. If I query it through python with os.environ it is not.
None of the results I found make reference that this should be an issue, neither on the PowerShell side nor on python's side. I have not restarted my machine since I honestly do not believe this is what should be done. I did restart my IDE in the hope that it is somehow caching the environment but thankfully it does not.
Any pointers would be great!

Setting an environment variable via PowerShell's $env: namespace defines it for the current process only.
Any Python scripts invoked directly from a PowerShell session would see such variables, however, because child processes inherit the caller's environment variables.
To persistently define a Windows environment variable at the machine level that all processes see, you must use .NET APIs directly (as of PowerShell 7.1):
# Note: Requires ELEVATION, due to setting at the *machine* level.
[Environment]::SetEnvironmentVariable('GOOGLE_ELEVATION_API', 'the_api-key', 'Machine')
Note that only future PowerShell sessions will see this variable, and the need to restart an application in order for it to see the new variable typically also applies to other running applications.
(The exception are those applications that actively listen for the WM_SETTINGCHANGE message and refresh their environment in response, which is what the Windows GUI shell (explorer.exe) does.)
For more information about persistently setting environment variables on Windows, see this answer.

Related

os.getenv('CORENLP_HOME') returning None and os.environ['CORENLP_HOME'] returning KeyError but echo $CORENLP_HOME returns a path in terminal

I am aware a lot of similar questions exist but I am unable to understand what is happening here. I am trying to follow instructions for this Stanford CoreNLP python wrapper here, one of the steps is to set theCORENLP_HOME environment variable.
I ran the command:
export CORENLP_HOME=/path/to/stanford-corenlp-full-2018-10-05
Restarted the terminal, or actually added to my ~/.bash_profile. Now when I do a echo $CORENLP_HOME in the terminal I am able to see the path correctly. But on the other hand, if the corenlp wrapper code tries to find the same path through python code it returns None.
So I separately checked two python commands, the wrapper code uses os.getenv():
import os
print(os.getenv('CORENLP_HOME')) #prints None
print(os.environ['CORENLP_HOME']) #Throws a KeyError exception
MacOS version: 10.15.4;Python: 3.7.6
I don't have a very deep understanding of environment variables in general, I want to understand what is happening here, or if I am missing something simple. Happy to provide more information!
Environment variables are not global in the UNIX process model. Each process is provided a set of environment variables by the parent process that starts it. That is typically a copy of the parent's environment variables. If you are not starting pycharm from the shell that ran the export command pycharm won't see that shell's environment variables.
The behavior you describe means you are not starting pycharm from the shell that did the export CORENLP_HOME=/path/to/stanford-corenlp-full-2018-10-05.
P.S., The UNIX process model also means that a process cannot modify the environment variables of a different process.

Access to system variable by using os.environ

I've created Windows system variable using below code:
import os
os.environ['BJT'] = 'HELLO'
But I can't see it in Advanced settings \ system variables Also I can't see it when I try to print it:
import os
print(os.environ['BJT'])
I thought that when I create system variable using os.environ it is created exacly like when I do it in system settings. Is it possible to create system variable from python code and access it even when I restart computer?
You need to call the system (with admin privileges) to create a system variable, you can use subprocess:
import subprocess
subprocess.run(['setx', 'BJT', '"HELLO"', '/M'])
Prior to python3.5 you will need to use process.call instead
There is a misunderstanding with what environment is. It is just a mapping of (string) variables that a process can pass to its children. Specifically a process can change its own environment (which will be used by its future children) but this will not change its parent's environment, nor even the environment of its already existing children if any.
In addition, Windows provides system and user environment variables which are used as the initial environment of any process. This are not changet by os.environ nor by putenv but only from the Windows API or the shell command setx.

Python change Windows Path (refresh Shell)

i have a Python script here and it is called from the Windows CMD.
It is executing some commands and also changing the Windows environment variables. Now after i changed them with the command "setx". I have to restart another Shell so the new variables are loaded into it.
Is it possible that the main shell from which i called my script can update the variables itself ?
Or is it possible to start another shell with the new variables and the script will continue in the new opened shell ?
Thanks
Each process has its own environment. When a process starts another process, the new process gets a (eventually modified) copy of its parent environment.
The rule is :
a process can modify its own environment - this modifications will be inherited by child processes started later
a process can modify (at start time) the environment of its child processes
a process can never modify its parent's environment (*)
So when you start a Python script from a cmd.exe :
the script can change its own environment and those changes will be visible by all subsequent commands of the script and all its children
the script cannot change the environment for its parent cmd.exe nor for subsequent commands of that cmd.exe
If you need to execute other batch commands after changing the environment, you will have to start a new cmd.exe for the python script and have this new shell execute the other commands, or directly execute a .bat file (both via subprocessmodule).
setx is a completely different thing : it updates the default environmnent that is given to processes started from windows explorer (including cmd.exe). That environment is stored permanently in Windows registry, and every change to it is broadcasted to all active processes ... that monitors it. Any windows GUI application can process it (and explorer does - that's how every explorer window know immediatly what is the current default environment), but console applications normaly do not.
(*) well it used to be possible for .com executable in old MS/DOS system and was even documented. It should be possible on Windows recent system through WriteProcessMemory API call but is absolutely non documented (thanks to eryksun for noticing)
You can't change the value of a environment variable.
Allow me to clarify: environment variables represent the variables set on the environment of a process when that process starts.
From the point-of-view of the new process, its environment is unchanging. Changing a variable on the environment (the process' parent) will not change the value of the environment variable seen by the process. Changing a variable on the process will not make it's environment see the change.
So, what can you change?
Variables set on your process. This is achieved in python by changing os.environ, or using set on the shell. Any changes will be seen by your process and any children you make (os.system, subprocess, most commands on the shell).
Variables set by the system (what SetX does). These changes will be seen by any new process launched directly by the system (Explorer, in Windows) after you change them.

os.environ doesn't see some variables

I have one problem with os.environ. I set some variables in my bat file (for example):
set MYDIR=%CURDIR%
Then I use set command in command line of Windows to check it. Everything is fine, my variable was added. But!
Then I run my Python script and use os.environ['MYDIR'] or os.getenv('MYDIR') but my envorinment variable doesn't show up!
Why does it happen?
My OS - Windows 7 x64, Python 2.5.4
Thanks.
Set works on session level. WinXP, use SETX from support tools http://www.microsoft.com/en-us/download/details.aspx?id=18546 to permanently set env variable.
Or use MyComputer>Properties>Advanced>Environment Variables to set user- and system- level variables.
Never used PyCharm, but breef scan through docs shows that you might be able to set script-level environment variables within PyCharm, look here http://www.jetbrains.com/pycharm/webhelp/run-debug-configuration-python.html

Setting environment variables in the current environment with python (win32com)

I'm trying to use python to set environment variables that will persist in Pythons parent environment, even after python exits back to the shell, but will not persist once the parent shell is closed. Opening a new shell should require that the python script be run again in order to set the environment correctly.
Based off the recommendations from this post, I'm trying to do this using the win32com python library. Unfortunately, I have very little experience with the win32 api.
Basically, I need a way to get a handle to the current environment, and set environment variables in such a way that they will persist in python's parent environment, but will not persist after the parent environment exits.
The linked post tells how to change the default environment which will affect new processes. It manipulates registry values.
"A process can never directly change the environment variables of another process that is not a child of that process", says MS documentation. So you'll never reach your stated goal from within a child process, Python or not.
It is impossible to change the environment of the parent, by design. The best you can do is have your program emit commands that alter the environment, and then the caller of your program needs to eval the output of your command.

Categories