복붙노트

[PYTHON] 파이썬에서 Windows 환경 변수를 수정하기위한 인터페이스

PYTHON

파이썬에서 Windows 환경 변수를 수정하기위한 인터페이스

어떻게하면 Python 스크립트에서 Windows 환경 변수를 지속적으로 수정할 수 있습니까? (setup.py 스크립트입니다)

나는 이것을 위해 사용할 표준 함수 나 모듈을 찾고있다. 나는 이미 그것을하는 레지스트리 방법에 익숙하지만, 그것에 관한 모든 의견도 환영합니다.

해결법

  1. ==============================

    1.setx를 사용하면 몇 가지 단점이 있는데, 특히 환경 변수에 추가하려고 할 때 (예 : setx PATH % Path %; C : \ mypath) 문제가 될 때마다 반복해서 경로에 추가합니다. 더 나쁜 것은 컴퓨터 경로 (HKEY_LOCAL_MACHINE에 저장 됨)와 사용자 경로 (HKEY_CURRENT_USER에 저장 됨)를 구분하지 않습니다. 명령 프롬프트에 표시되는 환경 변수는이 두 값의 연결로 구성됩니다. 그러므로 setx를 호출하기 전에 :

    setx를 사용하면 몇 가지 단점이 있는데, 특히 환경 변수에 추가하려고 할 때 (예 : setx PATH % Path %; C : \ mypath) 문제가 될 때마다 반복해서 경로에 추가합니다. 더 나쁜 것은 컴퓨터 경로 (HKEY_LOCAL_MACHINE에 저장 됨)와 사용자 경로 (HKEY_CURRENT_USER에 저장 됨)를 구분하지 않습니다. 명령 프롬프트에 표시되는 환경 변수는이 두 값의 연결로 구성됩니다. 그러므로 setx를 호출하기 전에 :

    user PATH == u
    machine PATH == m
    %PATH% == m;u
    
    > setx PATH %PATH%;new
    
    Calling setx sets the USER path by default, hence now:
    user PATH == m;u;new
    machine PATH == m
    %PATH% == m;m;u;new
    

    setx를 호출하여 PATH에 추가 할 때마다 시스템 경로가 % PATH % 환경 변수에 불가피하게 중복됩니다. 이러한 변경 사항은 영구적이며 재부팅에 의해 재설정되지 않으므로 시스템의 수명 기간 동안 누적됩니다.

    도스에서 이것을 보완하려고하는 것이 내 능력을 넘어선 다. 그래서 저는 파이썬으로 방향을 돌 렸습니다. 오늘 필자가 제기 한 해결책은 중복을 도입하지 않고 PATH에 추가하는 것을 포함하여 레지스트리를 조정하여 환경 변수를 설정하는 것입니다.

    from os import system, environ
    import win32con
    from win32gui import SendMessage
    from _winreg import (
        CloseKey, OpenKey, QueryValueEx, SetValueEx,
        HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE,
        KEY_ALL_ACCESS, KEY_READ, REG_EXPAND_SZ, REG_SZ
    )
    
    def env_keys(user=True):
        if user:
            root = HKEY_CURRENT_USER
            subkey = 'Environment'
        else:
            root = HKEY_LOCAL_MACHINE
            subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
        return root, subkey
    
    
    def get_env(name, user=True):
        root, subkey = env_keys(user)
        key = OpenKey(root, subkey, 0, KEY_READ)
        try:
            value, _ = QueryValueEx(key, name)
        except WindowsError:
            return ''
        return value
    
    
    def set_env(name, value):
        key = OpenKey(HKEY_CURRENT_USER, 'Environment', 0, KEY_ALL_ACCESS)
        SetValueEx(key, name, 0, REG_EXPAND_SZ, value)
        CloseKey(key)
        SendMessage(
            win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')
    
    
    def remove(paths, value):
        while value in paths:
            paths.remove(value)
    
    
    def unique(paths):
        unique = []
        for value in paths:
            if value not in unique:
                unique.append(value)
        return unique
    
    
    def prepend_env(name, values):
        for value in values:
            paths = get_env(name).split(';')
            remove(paths, '')
            paths = unique(paths)
            remove(paths, value)
            paths.insert(0, value)
            set_env(name, ';'.join(paths))
    
    
    def prepend_env_pathext(values):
        prepend_env('PathExt_User', values)
        pathext = ';'.join([
            get_env('PathExt_User'),
            get_env('PathExt', user=False)
        ])
        set_env('PathExt', pathext)
    
    
    
    set_env('Home', '%HomeDrive%%HomePath%')
    set_env('Docs', '%HomeDrive%%HomePath%\docs')
    set_env('Prompt', '$P$_$G$S')
    
    prepend_env('Path', [
        r'%SystemDrive%\cygwin\bin', # Add cygwin binaries to path
        r'%HomeDrive%%HomePath%\bin', # shortcuts and 'pass-through' bat files
        r'%HomeDrive%%HomePath%\docs\bin\mswin', # copies of standalone executables
    ])
    
    # allow running of these filetypes without having to type the extension
    prepend_env_pathext(['.lnk', '.exe.lnk', '.py'])
    

    현재 프로세스 나 상위 쉘에는 영향을 미치지 않지만 실행 후 열린 모든 cmd 창에 영향을 미치며 재부팅 할 필요가 없으며 복제본을 도입하지 않고도 여러 번 안전하게 편집하고 다시 실행할 수 있습니다.

  2. ==============================

    2.외부 Windows setx 명령을 사용하는 것만 큼 쉽습니다.

    외부 Windows setx 명령을 사용하는 것만 큼 쉽습니다.

    C:\>set NEWVAR
    Environment variable NEWVAR not defined
    
    C:\>python
    Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on
    win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os
    >>> os.system('setx NEWVAR newvalue')
    0
    >>> os.getenv('NEWVAR')
    >>> ^Z
    
    
    C:\>set NEWVAR
    Environment variable NEWVAR not defined
    

    이제 새 명령 프롬프트를 엽니 다.

    C:\>set NEWVAR
    NEWVAR=newvalue
    

    보시다시피 setx는 현재 세션이나 부모 프로세스 (첫 번째 명령 프롬프트)의 변수를 설정하지 않습니다. 그러나 그것은 미래의 프로세스를 위해 레지스트리에 변수를 지속적으로 설정합니다.

    나는 부모 프로세스의 환경을 전혀 바꿀 방법이 없다고 생각한다. (있다면, 나는 그것을 듣고 싶다.).

  3. ==============================

    3.프로그램을 통해 현재 DOS 세션의 환경을 변경하려고 시도한 것은 천년 전이었을 것입니다. 문제는 프로그램이 자체 DOS 셸 내에서 실행되므로 부모 환경에서 작동해야한다는 것입니다. DOS 컨트롤 블록에서 시작하여 메모리 제어 블록 체인을 따라 가면서 해당 부모 환경의 위치를 ​​찾습니다. 일단 이것을 어떻게하는지 알았 더라면, 환경 변수를 조작해야 할 필요성이 사라졌습니다. 아래에서 터보 파스칼 코드를 알려 드리겠습니다. 그러나 트릭을 수행하는 데는 적어도 세 가지 방법이 더 있습니다.

    프로그램을 통해 현재 DOS 세션의 환경을 변경하려고 시도한 것은 천년 전이었을 것입니다. 문제는 프로그램이 자체 DOS 셸 내에서 실행되므로 부모 환경에서 작동해야한다는 것입니다. DOS 컨트롤 블록에서 시작하여 메모리 제어 블록 체인을 따라 가면서 해당 부모 환경의 위치를 ​​찾습니다. 일단 이것을 어떻게하는지 알았 더라면, 환경 변수를 조작해야 할 필요성이 사라졌습니다. 아래에서 터보 파스칼 코드를 알려 드리겠습니다. 그러나 트릭을 수행하는 데는 적어도 세 가지 방법이 더 있습니다.

    그리고 여기에는 메모리 위치를보고하는 프로그램의 파스칼 코드 (네델란드어 사전과 파스칼 프로그래밍 북이 필요할 수 있음)가 있습니다. 그것은 여전히 ​​우리가 도스 5.00을 실행하고 있다고보고, Windows XP에서 작동하는 것 같습니다. 이것은 단지 시작에 불과하며, 선택된 환경을 조작하기 위해 많은 저수준 프로그래밍이 필요합니다. 포인터 구조가 정확 해 보일 수도 있기 때문에 1994 년의 환경 모델이 요즘에도 여전히 유지되는지 확신 할 수 없습니다 ...

    program MCBKETEN;
    uses dos, HexConv;
    
    {----------------------------------------------------------------------------}
    {  Programma: MCBKETEN.EXE                                                   }
    {  Broncode : MCBKETEN.PAS                                                   }
    {  Doel     : Tocht langs de MCB's met rapportage                            }
    {  Datum    : 11 januari 1994                                                }
    {  Auteur   : Meindert Meindertsma                                           }
    {  Versie   : 1.00                                                           }
    {----------------------------------------------------------------------------}
    
    type
       MCB_Ptr     = ^MCB;
    {  MCB_PtrPtr  = ^MCB_Ptr;  vervallen wegens DOS 2.11 -- zie verderop }
       MCB         = record
                        Signatuur    : char;
                        Eigenaar     : word;
                        Paragrafen   : word;
                        Gereserveerd : array[1..3] of byte;
                        Naam         : array[1..8] of char;
                     end;
       BlokPtr     = ^BlokRec;
       BlokRec     = record
                        Vorige       : BlokPtr;
                        DitSegment,
                        Paragrafen   : word;
                        Signatuur    : string[6];
                        Eigenaar,
                        Omgeving     : word;
                        Functie      : String4;
                        Oorsprong,
                        Pijl         : char;
                        KorteNaam    : string[8];
                        LangeNaam    : string;
                        Volgende     : BlokPtr;
                     end;
       PSP_Ptr     = ^PSP;
       PSP         = record
                        Vulsel1      : array[1..44] of byte;
                        Omgeving     : word;
                        Vulsel2      : array[47..256] of byte;
                     end;
    
    var
       Zone                  : string[5];
       ProgGevonden,
       EindeKeten,
       Dos3punt2             : boolean;
       Regs                  : registers;
       ActMCB                : MCB_Ptr;
       EersteSchakel, Schakel,
       LaatsteSchakel        : BlokPtr;
       ActPSP                : PSP_Ptr;
       EersteProg,
       Meester, Ouder,
       TerugkeerSegment,
       TerugkeerOffset,
       TerugkeerSegment2,
       OuderSegment          : word;
       Specificatie          : string[8];
       ReleaseNummer         : string[2];
       i                     : byte;
    
    
    {----------------------------------------------------------------------------}
    {  PROCEDURES EN FUNCTIES                                                    }
    {----------------------------------------------------------------------------}
    
    function Coda (Omgeving : word; Paragrafen : word) : string;
    
    var
       i            : longint;
       Vorige, Deze : char;
       Streng       : string;
    
    begin
       i    := 0;
       Deze := #0;
       repeat
          Vorige := Deze;
          Deze   := char (ptr (Omgeving, i)^);
          inc (i);
       until ((Vorige = #0) and (Deze = #0)) or (i div $10 >= Paragrafen);
       if (i + 3) div $10 < Paragrafen then begin
          Vorige := char (ptr (Omgeving, i)^);
          inc (i);
          Deze   := char (ptr (Omgeving, i)^);
          inc (i);
          if (Vorige = #01) and (Deze = #0) then begin
             Streng := '';
             Deze   := char (ptr (Omgeving, i)^);
             inc (i);
             while (Deze <> #0) and (i div $10 < Paragrafen) do begin
                Streng := Streng + Deze;
                Deze   := char (ptr (Omgeving, i)^);
                inc (i);
             end;
             Coda := Streng;
          end
          else Coda := '';
       end
       else Coda := '';
    end {Coda};
    
    
    {----------------------------------------------------------------------------}
    {  HOOFDPROGRAMMA                                                            }
    {----------------------------------------------------------------------------}
    
    BEGIN
      {----- Initiatie -----}
       Zone            := 'Lower';
       ProgGevonden    := FALSE;
       EindeKeten      := FALSE;
       Dos3punt2       := (dosversion >= $1403) and (dosversion <= $1D03);
       Meester         := $0000;
       Ouder           := $0000;
       Specificatie[0] := #8;
       str (hi (dosversion) : 2, ReleaseNummer);
       if ReleaseNummer[1] = ' ' then ReleaseNummer[1] := '0';
    
      {----- Pointer naar eerste MCB ophalen ------}
       Regs.AH := $52;  { functie $52 geeft adres van DOS Info Block in ES:BX }
       msdos (Regs);
    {  ActMCB := MCB_PtrPtr (ptr (Regs.ES, Regs.BX - 4))^;  NIET onder DOS 2.11  }
       ActMCB := ptr (word (ptr (Regs.ES, Regs.BX - 2)^), $0000);
    
      {----- MCB-keten doorlopen -----}
       new (EersteSchakel);
       EersteSchakel^.Vorige := nil;
       Schakel               := EersteSchakel;
       repeat
          with Schakel^ do begin
             DitSegment := seg (ActMCB^);
             Paragrafen := ActMCB^.Paragrafen;
             if DitSegment + Paragrafen >= $A000 then
                Zone    := 'Upper';
             Signatuur  := Zone + ActMCB^.Signatuur;
             Eigenaar   := ActMCB^.Eigenaar;
             ActPSP     := ptr (Eigenaar, 0);
             if not ProgGevonden then EersteProg := DitSegment + 1;
             if Eigenaar >= EersteProg
                then Omgeving := ActPSP^.Omgeving
                else Omgeving := 0;
             if DitSegment + 1 = Eigenaar then begin
                ProgGevonden  := TRUE;
                Functie       := 'Prog';
                KorteNaam[0]  := #0;
                while (ActMCB^.Naam[ ord (KorteNaam[0]) + 1 ] <> #0) and
                      (KorteNaam[0] < #8) do
                begin
                   inc (KorteNaam[0]);
                   KorteNaam[ ord (KorteNaam[0]) ] :=
                      ActMCB^.Naam[ ord (KorteNaam[0]) ];
                end;
                if Eigenaar = prefixseg then begin
                   TerugkeerSegment := word (ptr (prefixseg, $000C)^);
                   TerugkeerOffset  := word (ptr (prefixseg, $000A)^);
                   LangeNaam        := '-----> Terminate Vector = '     +
                                       WordHex (TerugkeerSegment) + ':' +
                                       WordHex (TerugkeerOffset )        ;
                end
                else
                   LangeNaam := '';
             end {if ÆProgØ}
             else begin
                if Eigenaar = $0008 then begin
                   if ActMCB^.Naam[1] = 'S' then
                      case ActMCB^.Naam[2] of
                         'D' : Functie := 'SysD';
                         'C' : Functie := 'SysP';
                         else  Functie := 'Data';
                      end {case}
                   else        Functie := 'Data';
                   KorteNaam := '';
                   LangeNaam := '';
                end {if Eigenaar = $0008}
                else begin
                   if DitSegment + 1 = Omgeving then begin
                      Functie   := 'Env ';
                      LangeNaam := Coda (Omgeving, Paragrafen);
                      if EersteProg = Eigenaar then Meester := Omgeving;
                   end {if ÆEnvØ}
                   else begin
                      move (ptr (DitSegment + 1, 0)^, Specificatie[1], 8);
                      if (Specificatie = 'PATH=' + #0 + 'CO') or
                         (Specificatie = 'COMSPEC='         ) or
                         (Specificatie = 'OS=DRDOS'         ) then
                      begin
                         Functie   := 'Env' + chr (39);
                         LangeNaam := Coda (DitSegment + 1, Paragrafen);
                         if (EersteProg = Eigenaar) and
                            (Meester    = $0000   )
                         then
                            Meester := DitSegment + 1;
                      end
                      else begin
                         if Eigenaar = 0
                            then Functie := 'Free'
                            else Functie := 'Data';
                         LangeNaam := '';
                         if (EersteProg = Eigenaar) and
                            (Meester    = $0000   )
                         then
                            Meester := DitSegment + 1;
                      end;
                   end {else: not ÆEnvØ};
                   KorteNaam := '';
                end {else: Eigenaar <> $0008};
             end {else: not ÆProgØ};
    
            {----- KorteNaam redigeren -----}
             for i := 1 to length (KorteNaam) do
                if KorteNaam[i] < #32 then KorteNaam[i] := '.';
             KorteNaam := KorteNaam + '        ';
    
            {----- Oorsprong vaststellen -----}
             if EersteProg = Eigenaar
                then Oorsprong := '*'
                else Oorsprong := ' ';
    
            {----- Actueel proces (uitgaande Pijl) vaststellen -----}
             if Eigenaar = prefixseg
                then Pijl := '>'
                else Pijl := ' ';
          end {with Schakel^};
    
         {----- MCB-opeenvolging onderzoeken / schakelverloop vaststellen -----}
          if (Zone = 'Upper') and (ActMCB^.Signatuur = 'Z') then begin
             Schakel^.Volgende := nil;
             EindeKeten        := TRUE;
          end
          else begin
             ActMCB := ptr (seg (ActMCB^) + ActMCB^.Paragrafen + 1, 0);
             if ((ActMCB^.Signatuur <> 'M') and (ActMCB^.Signatuur <> 'Z')) or
                ($FFFF - ActMCB^.Paragrafen < seg (ActMCB^)               )
             then begin
                Schakel^.Volgende := nil;
                EindeKeten        := TRUE;
             end
             else begin
                new (LaatsteSchakel);
                Schakel^.Volgende      := LaatsteSchakel;
                LaatsteSchakel^.Vorige := Schakel;
                Schakel                := LaatsteSchakel;
             end {else: (ÆMØ or ÆZØ) and Æteveel_ParagrafenØ};
          end {else: ÆLowerØ or not ÆZØ};
       until EindeKeten;
    
      {----- Terugtocht -----}
       while Schakel <> nil do with Schakel^ do begin
    
         {----- Ouder-proces vaststellen -----}
          TerugkeerSegment2 := TerugkeerSegment + (TerugkeerOffset div $10);
          if (DitSegment              <= TerugkeerSegment2) and
             (DitSegment + Paragrafen >= TerugkeerSegment2)
          then
             OuderSegment := Eigenaar;
    
         {----- Meester-omgeving markeren -----}
          if DitSegment + 1 = Meester then Oorsprong := 'M';
    
         {----- Schakel-verloop -----}
          Schakel := Schakel^.Vorige;
       end {while Schakel <> nil};
    
      {----- Rapportage -----}
       writeln ('Chain of Memory Control Blocks in DOS version ',
                lo (dosversion), '.', ReleaseNummer, ':');
       writeln;
       writeln ('MCB@ #Par Signat PSP@ Env@ Type !! Name     File');
       writeln ('---- ---- ------ ---- ---- ---- -- -------- ',
                '-----------------------------------');
       Schakel := EersteSchakel;
       while Schakel <> nil do with Schakel^ do begin
    
         {----- Ouder-omgeving vaststellen -----}
          if Eigenaar = OuderSegment then begin
             if not Dos3punt2 then begin
                if (Functie = 'Env ') then begin
                   Ouder := DitSegment + 1;
                   Pijl  := 'Û';
                end
                else
                   Pijl := '<';
             end {if not Dos3punt2}
             else begin
                if ((Functie = 'Env' + chr (39)) or (Functie = 'Data')) and
                   (Ouder    = $0000)
                then begin
                   Ouder := DitSegment + 1;
                   Pijl  := 'Û';
                end
                else
                   Pijl := '<';
             end {else: Dos3punt2};
          end {with Schakel^};
    
         {----- Keten-weergave -----}
          writeln (WordHex (DitSegment)        , ' ',
                   WordHex (Paragrafen)        , ' ',
                   Signatuur                   , ' ',
                   WordHex (Eigenaar)          , ' ',
                   WordHex (Omgeving)          , ' ',
                   Functie                     , ' ',
                   Oorsprong, Pijl             , ' ',
                   KorteNaam                   , ' ',
                   LangeNaam                        );
    
         {----- Schakel-verloop -----}
          Schakel := Schakel^.Volgende;
       end {while Schakel <> nil};
    
      {----- Afsluiting rapportage -----}
       writeln;
    
       write ('* = First command interpreter at ');
       if ProgGevonden
          then writeln (WordHex (EersteProg), ':0000')
          else writeln ('?');
    
       write ('M = Master environment        at ');
       if Meester > $0000
          then writeln (WordHex (Meester), ':0000')
          else writeln ('?');
    
       write ('< = Parent proces             at ');
       writeln (WordHex (OuderSegment), ':0000');
    
       write ('Û = Parent environment        at ');
       if Ouder > $0000
          then writeln (WordHex (Ouder), ':0000')
          else writeln ('?');
    
       writeln ('> = Current proces            at ',
                WordHex (prefixseg), ':0000');
    
       writeln ('    returns                   to ',
                WordHex (TerugkeerSegment), ':', WordHex (TerugkeerOffset));
    END.
    

    (위의 ASCII 127,이 프레젠테이션에 일부 ASCII / ANSI 번역 문제가있을 수 있습니다.)

  4. ==============================

    4.레지스트리 방법은 모든 것을 영구적으로 수정하고 싶다면 setup.py에 있기 때문에 여기에서 원하는 것입니다.

    레지스트리 방법은 모든 것을 영구적으로 수정하고 싶다면 setup.py에 있기 때문에 여기에서 원하는 것입니다.

    일시적으로 프로세스 만 수행하면 os.environ이 트릭입니다.

  5. ==============================

    5.os 모듈에는 getenv와 putenv 함수가있다. 그러나 putenv가 올바르게 작동하지 않고 Windows 레지스트리를 대신 사용해야하는 것으로 보입니다.

    os 모듈에는 getenv와 putenv 함수가있다. 그러나 putenv가 올바르게 작동하지 않고 Windows 레지스트리를 대신 사용해야하는 것으로 보입니다.

    이 토론 좀 봐.

  6. ==============================

    6.이 Python 스크립트 [*]는 사용자의 레지스트리에 아무런 권한도 부여되지 않은 경우 레지스트리의 GLOBAL 환경 변수를 수정하려고 시도한 다음 모든 윈도우에 변경 사항을 알립니다.

    이 Python 스크립트 [*]는 사용자의 레지스트리에 아무런 권한도 부여되지 않은 경우 레지스트리의 GLOBAL 환경 변수를 수정하려고 시도한 다음 모든 윈도우에 변경 사항을 알립니다.

    """
    Show/Modify/Append registry env-vars (ie `PATH`) and notify Windows-applications to pickup changes.
    
    First attempts to show/modify HKEY_LOCAL_MACHINE (all users), and 
    if not accessible due to admin-rights missing, fails-back 
    to HKEY_CURRENT_USER.
    Write and Delete operations do not proceed to user-tree if all-users succeed.
    
    Syntax: 
        {prog}                  : Print all env-vars. 
        {prog}  VARNAME         : Print value for VARNAME. 
        {prog}  VARNAME   VALUE : Set VALUE for VARNAME. 
        {prog}  +VARNAME  VALUE : Append VALUE in VARNAME delimeted with ';' (i.e. used for `PATH`). 
        {prog}  -VARNAME        : Delete env-var value. 
    
    Note that the current command-window will not be affected, 
    changes would apply only for new command-windows.
    """
    
    import winreg
    import os, sys, win32gui, win32con
    
    def reg_key(tree, path, varname):
        return '%s\%s:%s' % (tree, path, varname) 
    
    def reg_entry(tree, path, varname, value):
        return '%s=%s' % (reg_key(tree, path, varname), value)
    
    def query_value(key, varname):
        value, type_id = winreg.QueryValueEx(key, varname)
        return value
    
    def show_all(tree, path, key):
        i = 0
        while True:
            try:
                n,v,t = winreg.EnumValue(key, i)
                print(reg_entry(tree, path, n, v))
                i += 1
            except OSError:
                break ## Expected, this is how iteration ends.
    
    def notify_windows(action, tree, path, varname, value):
        win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')
        print("---%s %s" % (action, reg_entry(tree, path, varname, value)))
    
    def manage_registry_env_vars(varname=None, value=None):
        reg_keys = [
            ('HKEY_LOCAL_MACHINE', r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'),
            ('HKEY_CURRENT_USER', r'Environment'),
        ]
        for (tree_name, path) in reg_keys:
            tree = eval('winreg.%s'%tree_name)
            try:
                with winreg.ConnectRegistry(None, tree) as reg:
                    with winreg.OpenKey(reg, path, 0, winreg.KEY_ALL_ACCESS) as key:
                        if not varname:
                            show_all(tree_name, path, key)
                        else:
                            if not value:
                                if varname.startswith('-'):
                                    varname = varname[1:]
                                    value = query_value(key, varname)
                                    winreg.DeleteValue(key, varname)
                                    notify_windows("Deleted", tree_name, path, varname, value)
                                    break  ## Don't propagate into user-tree.
                                else:
                                    value = query_value(key, varname)
                                    print(reg_entry(tree_name, path, varname, value))
                            else:
                                if varname.startswith('+'):
                                    varname = varname[1:]
                                    value = query_value(key, varname) + ';' + value
                                winreg.SetValueEx(key, varname, 0, winreg.REG_EXPAND_SZ, value)
                                notify_windows("Updated", tree_name, path, varname, value)
                                break  ## Don't propagate into user-tree.
            except PermissionError as ex:
                print("!!!Cannot access %s due to: %s" % 
                        (reg_key(tree_name, path, varname), ex))
            except FileNotFoundError as ex:
                print("!!!Cannot find %s due to: %s" % 
                        (reg_key(tree_name, path, varname), ex))
    
    if __name__=='__main__':
        args = sys.argv
        argc = len(args)
        if argc > 3:
            print(__doc__.format(prog=args[0]))
            sys.exit()
    
        manage_registry_env_vars(*args[1:])
    

    다음은 현재 경로의 어딘가에 setenv.py라는 파일에 저장되었다고 가정 할 때 몇 가지 사용 예제입니다. 이 예제에서는 관리자 권한이 없으므로 로컬 사용자의 레지스트리 트리에만 영향을줍니다.

    > REM ## Print all env-vars
    > setenv.py
    !!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session   Manager\Environment:PATH due to: [WinError 5] Access is denied
    HKEY_CURRENT_USER\Environment:PATH=...
    ...
    
    > REM ## Query env-var:
    > setenv.py PATH C:\foo
    !!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session   Manager\Environment:PATH due to: [WinError 5] Access is denied
    !!!Cannot find HKEY_CURRENT_USER\Environment:PATH due to: [WinError 2] The system cannot find the file specified
    
    > REM ## Set env-var:
    > setenv.py PATH C:\foo
    !!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session   Manager\Environment:PATH due to: [WinError 5] Access is denied
    ---Set HKEY_CURRENT_USER\Environment:PATH=C:\foo
    
    > REM ## Append env-var:
    > setenv.py +PATH D:\Bar
    !!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session   Manager\Environment:PATH due to: [WinError 5] Access is denied
    ---Set HKEY_CURRENT_USER\Environment:PATH=C:\foo;D:\Bar
    
    > REM ## Delete env-var:
    > setenv.py -PATH
    !!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session   Manager\Environment:PATH due to: [WinError 5] Access is denied
    ---Deleted HKEY_CURRENT_USER\Environment:PATH
    

    [*] Adapted from : http://code.activestate.com/recipes/416087-persistent-environment-variables-on-windows/

  7. from https://stackoverflow.com/questions/1085852/interface-for-modifying-windows-environment-variables-from-python by cc-by-sa and MIT license