2009-01-28 16 views
7

A partir de mi previous question, ¿es posible hacer un script de Python que cambie persistentemente una variable de entorno de Windows?¿Puede una secuencia de comandos python cambiar persistentemente una variable de entorno de Windows? (elegantemente)

Los cambios en os.environ no persisten una vez que finaliza el intérprete de Python. Si estuviera presente scripting en UNIX, podría hacer algo como:

set foo=`myscript.py` 

Pero, por desgracia, cmd.exe no tiene nada que funciona como el comportamiento de back-garrapata de sh. He visto una solución muy largo aliento ... es aint bastante por lo que seguramente podemos mejorar en esto:

for /f "tokens=1* delims=" %%a in ('python ..\myscript.py') do set path=%path%;%%a 

Seguramente las mentes de Microsoft tienen una solución mejor que esto!

Nota: duplicado exacto de this question.

+0

No creo que la pregunta es un duplicado exacto ya que mi pregunta tiene que ver con sólo Windows. –

Respuesta

1

Su solución larga es probablemente la mejor idea; No creo que esto sea posible desde Python directamente. En este artículo se propone otra manera, utilizando un archivo por lotes temporal:

http://code.activestate.com/recipes/159462/

+5

Eso no cambia el medio ambiente persistentemente. Simplemente cambia una copia de las variables de entorno. – ralphtheninja

+0

¡Eso es lo que quiero! –

+2

@Salim Fadhley Si eso es lo que quieres, ¿por qué preguntas algo diferente en tu pregunta? Al aceptar la respuesta que no responde a la pregunta, engañas a las personas que buscan información ... –

3

Conjuntos de Windows Variables de entorno de valores almacenados en el Registro para cada proceso de forma independiente.

Sin embargo, hay una herramienta en el Windows XP Service Pack 2 Support Tools llamada setx.exe que le permite cambiar variables de entorno globales desde la línea de comandos.

+4

setx.exe también está instalado con Vista. Sin embargo, me da la impresión de que el póster original en realidad quería saber cómo modificar el entorno del proceso principal, no hacer que los valores de las variables de entorno persistan durante los reinicios. – bk1e

3

Mi solución usando win32api:

import os, sys, win32api, win32con 
'''Usage: appendenv.py envvar data_to_append''' 
def getenv_system(varname, default=None): 
    ''' 
    Author: Denis Barmenkov <barmenkov at bpc.ru> 

    Copyright: this code is free, but if you want to use it, 
       please keep this multiline comment along with function source. 
       Thank you. 

    2006-01-28 15:30 
    ''' 
    v = default 
    try: 
     rkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment') 
     try: 
      v = str(win32api.RegQueryValueEx(rkey, varname)[0]) 
      v = win32api.ExpandEnvironmentStrings(v) 
     except: 
      pass 
    finally: 
     win32api.RegCloseKey(rkey) 
    return v 

#My set function 
def setenv_system(varname, value): 
    try: 
     rkey = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment',0 ,win32con.KEY_WRITE) 
     try: 
      win32api.RegSetValueEx(rkey, varname, 0, win32con.REG_SZ, value) 
      return True 
     except Exception, (error): 
      pass 
    finally: 
     win32api.RegCloseKey(rkey) 
    return False 

if len(sys.argv) == 3: 
    value = getenv_system(sys.argv[1]) 
    if value: 
     setenv_system(sys.argv[1],value + ";" + sys.argv[2]) 
     print "OK! %s = %s" % (sys.argv[1], getenv_system(sys.argv[1])) 
    else: 
     print "ERROR: No such environment variable. (%s)" % sys.argv[1] 
else: 
    print "Usage: appendenv.py envvar data_to_append" 
+1

¿Es voluntario que el "obtener" use el CurrentControlSet y que el conjunto use ControlSet001? Si es así, ¿podrías explicar por qué? – SuperOli

+0

@SuperOli, son iguales en casi todos los casos, pero tienes razón, sería más seguro usar CurrentControlSet en 'conjunto'. No recuerdo por qué lo escribí así en aquel entonces. Voy a editar la respuesta. (Más información: http://support.microsoft.com/kb/100010) –

1

Este link ofrece una solución que utiliza el incorporado en winreg biblioteca.

(copypasta)

import sys 
from subprocess import check_call 
if sys.hexversion > 0x03000000: 
    import winreg 
else: 
    import _winreg as winreg 

class Win32Environment: 
    """Utility class to get/set windows environment variable""" 

    def __init__(self, scope): 
     assert scope in ('user', 'system') 
     self.scope = scope 
     if scope == 'user': 
      self.root = winreg.HKEY_CURRENT_USER 
      self.subkey = 'Environment' 
     else: 
      self.root = winreg.HKEY_LOCAL_MACHINE 
      self.subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment' 

    def getenv(self, name): 
     key = winreg.OpenKey(self.root, self.subkey, 0, winreg.KEY_READ) 
     try: 
      value, _ = winreg.QueryValueEx(key, name) 
     except WindowsError: 
      value = '' 
     return value 

    def setenv(self, name, value): 
     # Note: for 'system' scope, you must run this as Administrator 
     key = winreg.OpenKey(self.root, self.subkey, 0, winreg.KEY_ALL_ACCESS) 
     winreg.SetValueEx(key, name, 0, winreg.REG_EXPAND_SZ, value) 
     winreg.CloseKey(key) 
     # For some strange reason, calling SendMessage from the current process 
     # doesn't propagate environment changes at all. 
     # TODO: handle CalledProcessError (for assert) 
     check_call('''\ 
"%s" -c "import win32api, win32con; assert win32api.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')"''' % sys.executable) 
Cuestiones relacionadas