python, shell, environment variable
James T. Dennis
jadestar at idiom.com
Tue Jun 11 05:28:58 EDT 2002
oliver <fwang2 at yahoo.com> wrote:
> hi, folks,
> I am trying to get a set of python and bash scripts to work, and I
> constantly run into trouble with environment variables:
> First, my python script need to modify environment variable, say,
> PATH, and want to keep the modification even after the script is done.
> os.environ["PATH"]= ... doesn't seem to work, any idea?
Yes. You seem to have a fundamental misunderstanding about how
environment variables work (under UNIX and UNIX-like OSes, at least).
The environment is a region of your process' memory that is not
overwritten by an exec*() system call. Thus it is an efficient way
for a parent process to pass some (textual or textually encoded) data
to its children. The environment is *NOT* a share memory mechanism.
To execute Python your shell performed a fork() and then an exec*()
(some form of exec; it's not important which one). fork() creates a
new private address space for your new process, and address space that
is initially an (almost) exact copy of the parent's memory (except for
the portion of the stack or heap that's holding the return value to
the fork() call itself). [Please understand that this is a new
"virtual" address space; the actual physical memory pages are usually
shared through page table aliasing on modern processors/architectures
running modern kernels --- using a technique called CoW: copy on write].
So your assignments to os.environ["PATH"]=something are just happening
to your address space. They can't affect your parent's memory (that
would be a SEGV, segmentation violation; or it would require some form
of shared memory). The assignments would be visible in any processes
you created *under* your python process (os.popen('printenv') and search
for the PATH entry for one way to demonstrate that), and they should
remain set in that process (that was python) if you finish your script
with one of the os.exec*() functions (except for the exec*e() which
require you to explicitly prepare and pass a new environment to them).
> Second, it would be better if my python script can call bash shell and
> still keep the environment variable modification done by bash. I tried
> os.popen("source some_shell"), it doesn't work. ?
os.popen is creating yet another process; and the source command
therein is modifying popen's memory.
> Thanks for help.
> -oliver
This is a fundamental consequence of UNIX' fork()/exec*() and
memory management/protection model. It is a basic principle that
leads to several FAQs. It is something I have to emphasize at
considerable length in my shell scripting classes. It is also one
of the best examples of how important it is to understand the big
picture, the "model" of an architecture, an OS, a language, or any
other technology that one must control and use in any but the most
trivial ways. Once you understand how fork(), exec*() and *NIX
memory management works then you'd never have this question --- because
the answer would be so obvious. (When my son tattoos his arm, why
can't my grandpa read it off *his* arm? Because it's a different skin
that's being modified!).
More information about the Python-list
mailing list