This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: reload(os) fails for os.environ
Type: Stage:
Components: Windows Versions:
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: mhammond Nosy List: gvanrossum, mhammond, nobody, tim.peters
Priority: normal Keywords:

Created on 2001-09-21 10:05 by anonymous, last changed 2022-04-10 16:04 by admin. This issue is now closed.

Messages (10)
msg6621 - (view) Author: Nobody/Anonymous (nobody) Date: 2001-09-21 10:05

I used function KERNEL32::SetEnvironmentVariableA 
via Dynawrap.dll from
http://cwashington.netreach.net/main_site/
downloads/default.asp?topic=a-m
to add an new entry.

Then I tested the result with a scripting host 
component and the new entry was shown. But not working 
was this:

reload(os)
os.environ


PythonWin 2.1 (#15, Jun 18 2001, 21:42:28) [MSC 32 bit 
(Intel)] on win32.
Portions Copyright 1994-2001 Mark Hammond 
(MarkH@ActiveState.com) - see 'Help/About PythonWin' 
for further copyright information.
>>> import os
>>> os.environ
{'SNDSCAPE': 'C:\\WINDOWS', 'CMDLINE': 'WIN', 'PATH': '
C:\\PROGRAMME\\PYTHON21
\\;C:\\WINDOWS;C:\\WINDOWS\\COMMAND', 'TEMP': 'C:\\WIND
OWS\\TEMP', 'COMSPEC': 'C:\\WINDOWS\\COMMAND.COM', 'PRO
MPT': '$p$g', 'WINBOOTDIR': 'C:\\WINDOWS', 'WINDIR': 'C
:\\WINDOWS', 'TMP': 'C:\\WINDOWS\\TEMP'}
>>> 
>>> from win32com.client import Dispatch
>>> dw = Dispatch("DynamicWrapper")
>>> dw.Register
("KERNEL32.DLL", "SetEnvironmentVariableA", "i=ss", "f=
s", "r=l")
1
>>> dw.SetEnvironmentVariableA
("MyNewEntry", "MyNewValue")
1
>>> reload(os)
<module 'os' from 'c:\programme\python21\lib\os.pyc'>
>>> os.environ
{'SNDSCAPE': 'C:\\WINDOWS', 'CMDLINE': 'WIN', 'PATH': '
C:\\PROGRAMME\\PYTHON21
\\;C:\\WINDOWS;C:\\WINDOWS\\COMMAND', 'TEMP': 'C:\\WIND
OWS\\TEMP', 'COMSPEC': 'C:\\WINDOWS\\COMMAND.COM', 'PRO
MPT': '$p$g', 'WINBOOTDIR': 'C:\\WINDOWS', 'WINDIR': 'C
:\\WINDOWS', 'TMP': 'C:\\WINDOWS\\TEMP'}
>>> 
>>> sh = Dispatch("WScript.Shell")
>>> for string in sh.Environment._NewEnum():
... 	print string
... 	
TMP=C:\WINDOWS\TEMP
TEMP=C:\WINDOWS\TEMP
PROMPT=$p$g
winbootdir=C:\WINDOWS
COMSPEC=C:\WINDOWS\COMMAND.COM
PATH=C:\PROGRAMME\PYTHON21
\;C:\WINDOWS;C:\WINDOWS\COMMAND
CMDLINE=WIN
windir=C:\WINDOWS
SNDSCAPE=C:\WINDOWS
MYNEWENTRY=MyNewValue
>>> 
msg6622 - (view) Author: Nobody/Anonymous (nobody) Date: 2001-09-21 10:08
Logged In: NO 

This Bug was submitted by Markus Daniel (Spacy73)
msg6623 - (view) Author: Nobody/Anonymous (nobody) Date: 2001-09-21 10:18
Logged In: NO 

Markus_Daniel@gmx.de
msg6624 - (view) Author: Nobody/Anonymous (nobody) Date: 2001-09-21 12:00
Logged In: NO 

This is an altenative way to change the environment:

from win32com.client import Dispatch
sh = Dispatch("WScript.Shell")
sh.Environment['MYNEWENTRY'] = "bla-bla"
print sh.Environment['MYNEWENTRY']
msg6625 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2001-09-21 21:47
Logged In: YES 
user_id=31435

Reassigned to MarkH.  I haven't figured out what the 
complaint is, but it looks like it has to do with the Win32 
extensions.
msg6626 - (view) Author: Mark Hammond (mhammond) * (Python committer) Date: 2001-09-22 00:01
Logged In: YES 
user_id=14198

The complaint is that when the environment is set via the 
win32 API, os.environ appears to not pick up the new 
setting.

I have no idea why this is, but it is not Python's fault.  
Python uses the C runtime library, and there i snot much we 
can do about that.  I don't have time to try and locate the 
CRTL source code and figure out why either.  Marking 
as "Wont Fix"
msg6627 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2001-09-22 00:29
Logged In: YES 
user_id=31435

Ah!  Good call.  WRT VC's putenv, the MS docs say:

"""
_putenv and _wputenv affect only the environment that is 
local to the current process; you cannot use them to modify 
the command-level environment. That is, these functions 
operate only on data structures accessible to the run-time 
library and not on the environment segment created for a 
process by the operating system. When the current process 
terminates, the environment reverts to the level of the 
calling process (in most cases, the operating-system 
level). However, the modified environment can be passed to 
any new processes created by _spawn, _exec, or system, and 
these new processes get any new items added by _putenv and 
_wputenv. 
"""

Sounds like the msvcrt-level env functions work with a copy 
of the process env block captured at process creation time.

As usual, a Bad Idea to try to use envars on Windows ...
msg6628 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2001-09-22 17:33
Logged In: YES 
user_id=6380

The reason is trivial. reload(os) doesn't magically cause
reload(nt), and it's the nt module (whose source is
posixmodule.c) that computes the 'environ' dictionary.  I
betcha a dollar that if you reload(nt) and then reload(os),
the environment is fixed.  But why would you want to do
that?  Changing os.environ should automatically call
_putenv(); if it doesn't, submit a separate bug report.

The MS docs are trying to explain that the environment
semantics are the same as in Unix (you can't change your
shell's environment, but child processes do inherit yours).  

In my experience envars work fine in Windows.
msg6629 - (view) Author: Mark Hammond (mhammond) * (Python committer) Date: 2001-09-23 04:45
Logged In: YES 
user_id=14198

I think the SDK description Tim posted was clear that 
setenv does not modify the process environment.  To prove 
this, I wrote the test code at the end (and output past it).

It shows that using "::SetEnvironmentVariable()" will not 
have the value reflected in the CRTL (ie, getenv() will not 
see the new value)

However, using putenv() *does* reflect the value back to 
the Win32 API - so GetEnvironmentVariable *does* see the 
value set by putenv.

So I think Python is using the correct API, and can't fix 
the behaviour.

int main()
{
    static char buffer[128];
    char * val = getenv("FOO");
    printf("When starting, FOO=%s\n", val);
    SetEnvironmentVariable("FOO", "SetEnvironmentVariable");
    
    GetEnvironmentVariable("FOO", buffer, sizeof
(buffer)/sizeof(buffer[0]));
    val = buffer;
    printf("After set, GetEnvironmentVariable reports FOO=%
s\n", val);
    val = getenv("FOO");
    printf("After set, getenv reports FOO=%s\n", val);

    putenv("FOO=_putenv");
    
    GetEnvironmentVariable("FOO", buffer, sizeof
(buffer)/sizeof(buffer[0]));
    val = buffer;
    printf("After _putenv set, GetEnvironmentVariable 
reports FOO=%s\n", val);
    val = getenv("FOO");
    printf("After _putenv set, getenv reports FOO=%s\n", 
val);
    return 0;
}

Output:
When starting, FOO=(null)
After set, GetEnvironmentVariable reports 
FOO=SetEnvironmentVariable
After set, getenv reports FOO=(null)
After _putenv set, GetEnvironmentVariable reports 
FOO=_putenv
After _putenv set, getenv reports FOO=_putenv
msg6630 - (view) Author: Mark Hammond (mhammond) * (Python committer) Date: 2001-09-23 07:00
Logged In: YES 
user_id=14198

*sigh* - OK - the SDK docs appear wrong, but the main point 
is still valid.

_putenv() does indeed modify the process environment, as 
the test program I wrote demonstrated.  However, 
SetEnvironmentVariable() does *not* get reflected in the 
CRTL environment.
History
Date User Action Args
2022-04-10 16:04:27adminsetgithub: 35217
2001-09-21 10:05:38anonymouscreate