Skip to content

os.environ['VAR'] = '' is not portable (windows) #158694

Description

@asottile

Bug report

import os

def test_env(x):
    print(f'setting X={x}')
    os.environ['X'] = x
    assert os.environ.get('X') == x, os.environ.get('X')
    os.reload_environ()
    assert os.environ.get('X') == x, os.environ.get('X')

test_env('1')
test_env('')

it is possible to set an empty environment variable on windows (via SetEnvironmentVariableW) -- but not from python's os.environ . there's more context here: pre-commit/pre-commit#3766 (comment) (due to _wputenv)

on linux (I only attempted with amd64 ubuntu 26.04) the script above succeeds -- on windows it fails with the following:

>python t.py
setting X=1
setting X=
Traceback (most recent call last):
  File "C:\Users\asott\workspace\t.py", line 11, in <module>
    test_env('')
    ~~~~~~~~^^^^
  File "C:\Users\asott\workspace\t.py", line 8, in test_env
    assert os.environ.get('X') == x, os.environ.get('X')
           ^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: None

note also that this bug also results in os.environ diverging from the real environment (line 8 above is an assertion failure only after os.reload_environ())

note that I've only marked "3.14" as the version I tested on -- I suspect this also affects mainline but I do not have an easy way to build on the machine I'm working on at the moment

CPython versions tested on:

3.14

Operating systems tested on:

Windows

Linked PRs

Activity

  1. aisk commented on Oct 4, 2026

    @aisk
    Member

    This was discussed before in gh-83594. Using SetEnvironmentVariableW would solve this, but it bypasses the CRT, so C code in the same process that calls getenv() won't see the variable. That's why _wputenv is used, which leads to the current inconsistency.

    I think it might be reasonable to just treat this as platform-specific behavior and document it? It's easy to work around at the application level.

    Another option is to combine the two APIs for empty values, but that's a bit messy.

    So I'd like to hear what @eryksun and @zooba think.

  2. asottile commented on Oct 4, 2026

    @asottile
    ContributorAuthor

    seems wrong to me to care that the CRT environ is in sync over os.environ itself

  3. zooba commented on Oct 5, 2026

    @zooba
    Member

    seems wrong to me to care that the CRT environ is in sync over os.environ itself

    Perhaps, but it's a long-standing deliberate behaviour, and to change it will require a deprecation period.

    We care about the CRT state because embedders will share that state with the runtime they've loaded. That's been very intentional for a long time.

    Adding an additional SetEnvironmentVariable call to set an empty variable after wputenv has deleted it would be possible, I guess. I have no idea whether that will achieve what is desired here (as far as I can tell, the original "problem" is that there is code that expects an empty environment variable to exist, which just means it's made an assumption that isn't necessarily true and doesn't necessarily mean that it's useful or important to work that way - but I'm totally missing context on this, since I've only got this issue and the linked one to look at).

  4. added a commit that references this issue on Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions