-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
os.environ should preserve the case of the OS keys ? #73010
Comments
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: 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. Line 733 in b82a5a6
|
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? |
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. |
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. |
I've come across a few problems when passing a modified |
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 ? |
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. |
On Windows, maybe the @total_ordering
class _CaseInsensitiveString(str):
def __eq__(self, other):
if not isinstance(other, str):
return NotImplemented
return path.normcase(self) == path.normcase(other)
def __lt__(self, other):
if not isinstance(other, str):
return NotImplemented
return path.normcase(self) < path.normcase(other)
def __hash__(self):
return hash(path.normcase(self)) Change def encodekey(key):
return _CaseInsensitiveString(encode(key)) in which |
This issue should be marked dependent on bpo-43702 or bpo-46862, since fixing it could break third-party code unless they're fixed first.
Right now, it's not a good workaround because it contains the environment at the time the interpreter was started, not the current environment. On Posix, _Environ takes a reference to posix.environ and uses it directly, so it does get updated. On Windows, _Environ gets a rewritten dictionary and nt.environ is just a space-wasting attractive nuisance. I think it should be replaced with getenviron() which builds a dict from the environment block each time it's called. But posix.environ is documented (though nt.environ isn't), so maybe not.
I think there should be a public class like this. It could be useful to email.message.Message and its clients like urllib. They currently store headers in a list and every operation is O(n). The semantics are tricky. As written, it violates the requirement that equal objects have equal hashes. To fix that, you'd have to make every CIS compare unequal to every str. At that point, it probably shouldn't be a str subclass, which also has the advantage that it's not limited to strings. It can be a generic compare-by-key wrapper. |
I wrote a basic implementation of The problem of case-insensitive names in file/registry paths and environment variables should be addressed with
Note that in some cases the "current environment" is the process environment, which isn't necessarily consistent with On POSIX, On Windows, |
If you don't have duplicate entries, and want to just uppercase all envs, you can do it with this one-liner: |
Given this is now documented that keys are always converted to upper case in #101754, should we close this? @zooba @brettcannon |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: