Может ли скрипт Python постоянно изменять переменную среды Windows? (элегантно) - PullRequest
8 голосов
/ 28 января 2009

Исходя из моего предыдущего вопроса , возможно ли создать скрипт Python, который постоянно изменяет переменную среды Windows?

Изменения в os.environ не сохраняются после завершения работы интерпретатора Python. Если бы я писал это в UNIX, я мог бы сделать что-то вроде:

set foo=`myscript.py`

Но, увы, cmd.exe не имеет ничего, что бы работало как поведение тика назад. Я видел очень затянутое решение ... это не так уж точно, мы можем улучшить это:

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

Конечно, у Microsoft есть лучшее решение, чем это!

Примечание : точная копия этого вопроса .

Ответы [ 5 ]

5 голосов
/ 28 января 2009

Возможно, вы захотите попробовать Python Win32 Extensions , разработанный Марком Хаммондом, который включен в ActivePython (или может быть установлен отдельно). Вы можете научиться выполнять множество задач, связанных с Windows, в книге Хаммонда и Робинсона .

Используя PyWin32 для доступа к окнам COM-объекты , программа Python может использовать Свойство среды объекта WScript.Shell - набор переменных среды.

3 голосов
/ 27 февраля 2009

Мое решение с использованием 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"
3 голосов
/ 28 января 2009

Windows устанавливает переменные окружения из значений, хранящихся в реестре, для каждого процесса независимо.

Однако в средствах поддержки Windows XP с пакетом обновления 2 (SP2) имеется инструмент с именем setx.exe, который позволяет изменять глобальные переменные среды из командной строки.

2 голосов
/ 28 октября 2013

Эта ссылка предоставляет решение, использующее встроенную библиотеку winreg.

(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)
1 голос
/ 28 января 2009

Ваше долгосрочное решение, вероятно, лучшая идея; Я не верю, что это возможно из Python напрямую. Эта статья предлагает другой способ, используя временный пакетный файл:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...