Can it be changed for the current process by simply setting it to a new value like this?
os.environ['PYTHONHASHSEED'] = 'random'
It depends by what you mean.
If you mean to change the behaviour of the current interpreter than the answer is no:
Modifying os.environ isn't reliable, since in some OSes you cannot modify the environment (see the documentation for os.environ).
Environmental variables are checked only when launching the interpreter, so changing them afterwards will not have any effects for the current python instance. From the documentation:
These environment variables influence Python’s behavior, they are
processed before the command-line switches other than -E or -I.
(which implies they are only checked when launching the interpreter, well before any user-code is run).
AFAIK, the random hash seed cannot be set dynamically, so you have to restart the interpreter if you want to activate hash randomization.
If you mean to make new processes spawned by the current interpreter behave as if that value was set before, then yes, assuming that you are running on a platform that supports putenv. When spawning a new process, by default, it inherits the environment of the current process. You can test this using a simple script:
#check_environ.py
import os
import subprocess
os.environ['A'] = '1'
proc = subprocess.call(['python', '-c', 'import os;print(os.environ["A"])'])
Which yields:
$ python check_environ.py
1
Note that there exist known bugs in putenv implementations (e.g. in Mac OS X), where it leaks memory. So modifying the environment is something you want to avoid as much as possible.
Related
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.
I am trying to overwrite to environment variables in Python. I can read the value and then write the value and print the updated value. But then if I check the value in command line its still the original value. Why is that?
First, I create the variable
export MYVAR=old_val
My test script myvar.py
#!/usr/bin/env python3
import os
print (os.environ['MYVAR'])
os.environ['MYVAR'] = "new_val"
print (os.environ['MYVAR'])
Outputs
$ ./myvar.py
old_val
new_val
$ echo $MYVAR
old_val
As you can see, the last line of the output still shows the old_val
Short version:
The python script changes its environment. However this does not affect the environment of the parent process (The shell)
Long version:
Well this is a well know, but quite confusing problem.
What you have to know is, that there is not the environment, each process has its own environment.
So in your example above the shell (where you type your code) has one environment.
When you call ./myvar.py, a copy of the current environment is created and passed to your python script.
Your code 'only' changes this copy of the environment.
As soon as the python script is finished this copy is destroyed and the shell will see its initial unmodified environment.
This is true for most operating systems (Windows, Linux, MS-DOS, ...)
In other words: No child process can change the environment of the process, that called it.
In bash there is a trick, where you source a script instead of calling it as a process.
However if your python script starts another process (for example /bin/bash), then the child process would see the modified environment.
You started a new process that changed its environment and exited. That's all really.
You shouldn't expect that to affect the process you started it from (your shell).
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.
Is there a command I can use in a Python file to clear all variables?
I've been searching for this for a while but all I could find was to use %reset. However, this only seems to work in IPython, but not when I try to run a python file.
FYI, I am working with the free version of enthought canopy.
[ADDED from comments:] I have several python files I run, which might have shared variables. I would like to be able to clear all variables before running any of the files to guarantee that I have defined variables correctly and that they are taking the correct values.
tl;dr -- what you describe is not an issue.
But it is worth understanding, to avoid other points of confusion:
1) When you are running IPython (including Canopy's Python pane, which is a standard IPython QtConsole), IPython has its own global namespace (list of variables and modules and functions etc) which is distinct from the namespace of the scripts which run within it. This can be confusing, but it is actually a feature.
2) When you run each script normally, it starts with an empty namespace, just as if it were running in plain Python. That's why your concern is a non-issue. But this can also confuse beginners, because your script also doesn't know about the modules that have already been imported in IPython. For more on this, see this article.
3) When the script completes, its global namespace is copied into the IPython global namespace (overwriting any same-named variables that were already there).
4) Thus normal visibility is one-way -- IPython sees the results of the scripts that you ran, so you can work with them more at the prompt, but your scripts don't see the results of previous scripts that you ran (not even the same script), or of anything you do at the prompt.
5) There is one huge difference, though, from when you run your script in plain Python. Namely, IPython itself is not re-initialized between runs (unless you reset the kernel), and in particular, any modules that have been imported are still initialized and won't be re-loaded or re-initialized when you import them in subsequent scripts. For more info, see this article.
6) A side note: The %run command can be given a -i option to make namespace visibility 2-way, so your scripts will start in the IPython namespace (as I think you were expecting), but this is unusual and not the default, since usually one wants to ensure (as you apparently do) that the script is running "clean". The main reason to use this option would be to have your scripts build on each other, but there are more robust, portable ways to achieve this (namely passing variable names from the IPython namespace as parameters to the functions that you define in your script).
I have a requirement where 1 process sets a value as environment variable and I read that value in python using
os.environ
As per python doc:
This mapping is captured the first
time the os module is imported,
typically during Python startup as
part of processing site.py. Changes to
the environment made after this time
are not reflected in os.environ,
except for changes made by modifying
os.environ directly.
My problem is the process set/change the variable every time it calls the python script.
Please tell me a way to read the changed value.
Thanks,
I guess you can use os.getenv() to get the value of an environment variable any time, and this will reflect the most up-to-date state.
Update: note that there is no such thing as one "global" environment, at least not on Linux. Quoting Wikipedia:
In all Unix and Unix-like systems, each process has its own private set of environment variables. By default, when a process is created it inherits a duplicate environment of its parent process, except for explicit changes made by the parent when it creates the child.
Therefore, if you launch (fork) two processes from the same parent process (such as bash), and change an environment variable in one of the processes, the other process won't see it because it uses another copy of the environment of the parent process. Similarly, if you change the environment in the parent process after having launched the child processes, the child processes won't see the change because they have already created their private copy of the environment.
If your process sets/updates an environment variable and then calls the Python script, you would see the updated value in your Python script. But if these are parallel processes and the environment variable gets modified when the Python script is running then the updates to the environemnt variable is not seen in the Python script.