classification
Title: os.environ should preserve the case of the OS keys ?
Type: Stage:
Components: Windows Versions: Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: eryksun, larry, loewis, paul.moore, r.david.murray, steve.dower, tim.golden, tzickel, zach.ware
Priority: normal Keywords:

Created on 2016-11-28 18:55 by tzickel, last changed 2016-11-28 21:38 by steve.dower.

Messages (7)
msg281906 - (view) Author: (tzickel) * Date: 2016-11-28 18:55
In Windows, python's os.environ currently handles the case sensitivity different that the OS. While it's true that the OS is case insensitive, it does preserve the case that you first set it as.

For example:
C:\Users\user>set aSD=Blah
C:\Users\user>set asd
aSD=Blah

But in python:
>>> import os
>>> 'aSD' in os.environ.keys()
False

Today as more people pass environment variables to processes, it's better to behave as the OS does. Basically I think that os.environ (both in 2.7 and 3) should preserve the case as well (for when you need to access / iterate over the keys or set a key), but ignore it when you get a key.

https://github.com/python/cpython/blob/b82a5a65caa5b0f0efccaf2bbea94f1eba19a54d/Lib/os.py#L733
msg281909 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2016-11-28 19:03
That unfortunately would probably break existing code.  It does seem reasonable that case should be ignored on get, though, if the OS does so.  So making your 'in' statement work might be acceptable, backward compatibility wise.  Probably only in 3.7, though.

Is it the OS that ignores case, or just the shell?
msg281910 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2016-11-28 19:11
This works fine in Python 3, and also Python 2.7 *unless* you call .keys().

PS D:\> py -2.7
Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:24:40) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> 'path' in os.environ, 'path' in os.environ.keys()
(True, False)

PS D:\> py
Python 3.6.0b4 (default, Nov 22 2016, 05:30:12) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> 'path' in os.environ, 'path' in os.environ.keys()
(True, True)

I suspect at this point, we aren't going to change this in Python 2.7 unless someone comes up with an incredibly motivating issue.
msg281912 - (view) Author: (tzickel) * Date: 2016-11-28 19:29
My issue is that somebody wants to pass a few dict like environment variables as some prefix_key=value but he wants to preserve the case of the key for usage in python so the .keys() space needs to be enumerated.

A workaround for this issue can be importing nt and using nt.environ which preserves the cases.
msg281914 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2016-11-28 20:35
I've come across a few problems when passing a modified os.environ.copy() to a child process via subprocess.Popen. Ideally it shouldn't be an issue, as long as the OS or C runtime functions are used, but some troublesome programs do their own case-sensitive search for environment variables (definitely a bug). In such cases the simplest workaround is to use nt.environ.copy(), but this doesn't include any changes in the environment since startup.
msg281915 - (view) Author: (tzickel) * Date: 2016-11-28 20:39
Steve, I've checked in Python 3.5.2, and os.environ.keys() still uppercases everything when scanning (for my use case). Has it changed since then ?
msg281918 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2016-11-28 21:38
Ah, I see what you mean. In this case, we could change how the case-insensitivity is handled here, but it would only be applicable to 3.7. I'm not opposed to changing the default behavior here, but it does kind of bring up the mapping dict discussion again.

If case is important to your application, environment variables are probably the wrong way to go about passing them in anyway. Either use the value of the variable rather than the key, or find a different approach. Given 'nt.environ' is available without case remapping, I think that's the best workaround.
History
Date User Action Args
2016-11-28 21:38:12steve.dowersetmessages: + msg281918
versions: + Python 3.7, - Python 2.7
2016-11-28 20:39:59tzickelsetmessages: + msg281915
2016-11-28 20:35:54eryksunsetnosy: + eryksun
messages: + msg281914
2016-11-28 19:29:04tzickelsetmessages: + msg281912
2016-11-28 19:11:48steve.dowersetmessages: + msg281910
versions: - Python 3.7
2016-11-28 19:03:39r.david.murraysetnosy: + r.david.murray
messages: + msg281909
2016-11-28 18:55:46tzickelcreate