简体   繁体   English

如何在 Python 中读出*新*操作系统环境变量?

[英]How to read out *new* OS environment variables in Python?

Reading out OS environment variables in Python is a piece of cake.在 Python 中读取操作系统环境变量是小菜一碟。 Try out the following three code lines to read out the 'PATH' variable in Windows:尝试使用以下三行代码读取 Windows 中的'PATH'变量:

    #################
    #   PYTHON 3.5  #
    #################
    >> import os
    >> pathVar = os.getenv('Path')
    >> print(pathVar)

        C:\Anaconda3\Library\bin;C:\Anaconda3\Library\bin;
        C:\WINDOWS\system32;C:\Anaconda3\Scripts;C:\Apps\SysGCC\arm-eabi\bin;
        ...

Now make a small change in the 'PATH' variable.现在对'PATH'变量做一个小改动。 You can find them in:您可以在以下位置找到它们:

Control Panel >> System and Security >> System >> Advanced system settings >> Environment variables控制面板>>系统和安全>>系统>>高级系统设置>>环境变量

If you run the same code in Python, the change is not visible!如果您在 Python 中运行相同的代码,则更改不可见! You've got to close down the terminal in which you started the Python session.您必须关闭启动 Python 会话的终端。 When you restart it, and run the code again, the change will be visible.当您重新启动它并再次运行代码时,更改将可见。

Is there a way to see the change immediately - without the need to close python?有没有办法立即看到变化——而无需关闭python? This is important for the application that I'm building.这对于我正在构建的应用程序很重要。

Thank you so much :-)非常感谢:-)


EDIT :编辑:

Martijn Pieters showed me the following link: Is there a command to refresh environment variables from the command prompt in Windows? Martijn Pieters 向我展示了以下链接: Windows 中是否有从命令提示符刷新环境变量的命令?

There are many options mentioned in that link.该链接中提到了许多选项。 I chose the following one (because it is just a batch file, no extra dependencies):我选择了以下一个(因为它只是一个批处理文件,没有额外的依赖项):

            REM   --------------------------------------------
            REM   |            refreshEnv.bat                |
            REM   --------------------------------------------
    @ECHO OFF
    REM Source found on https://github.com/DieterDePaepe/windows-scripts
    REM Please share any improvements made!

    REM Code inspired by https://stackoverflow.com/questions/171588/is-there-a-command-to-refresh-environment-variables-from-the-command-prompt-in-w

    IF [%1]==[/?] GOTO :help
    IF [%1]==[/help] GOTO :help
    IF [%1]==[--help] GOTO :help
    IF [%1]==[] GOTO :main

    ECHO Unknown command: %1
    EXIT /b 1 

    :help
    ECHO Refresh the environment variables in the console.
    ECHO.
    ECHO   refreshEnv       Refresh all environment variables.
    ECHO   refreshEnv /?        Display this help.
    GOTO :EOF

    :main
    REM Because the environment variables may refer to other variables, we need a 2-step approach.
    REM One option is to use delayed variable evaluation, but this forces use of SETLOCAL and
    REM may pose problems for files with an '!' in the name.
    REM The option used here is to create a temporary batch file that will define all the variables.

    REM Check to make sure we dont overwrite an actual file.
    IF EXIST %TEMP%\__refreshEnvironment.bat (
      ECHO Environment refresh failed!
      ECHO.
      ECHO This script uses a temporary file "%TEMP%\__refreshEnvironment.bat", which already exists. The script was aborted in order to prevent accidental data loss. Delete this file to enable this script.
      EXIT /b 1
    )

    REM Read the system environment variables from the registry.
    FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"`) DO (
      REM /I -> ignore casing, since PATH may also be called Path
      IF /I NOT [%%I]==[PATH] (
        ECHO SET %%I=%%K>>%TEMP%\__refreshEnvironment.bat
      )
    )

    REM Read the user environment variables from the registry.
    FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY HKCU\Environment`) DO (
      REM /I -> ignore casing, since PATH may also be called Path
      IF /I NOT [%%I]==[PATH] (
        ECHO SET %%I=%%K>>%TEMP%\__refreshEnvironment.bat
      )
    )

    REM PATH is a special variable: it is automatically merged based on the values in the
    REM system and user variables.
    REM Read the PATH variable from the system and user environment variables.
    FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH`) DO (
      ECHO SET PATH=%%K>>%TEMP%\__refreshEnvironment.bat
    )
    FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY HKCU\Environment /v PATH`) DO (
      ECHO SET PATH=%%PATH%%;%%K>>%TEMP%\__refreshEnvironment.bat
    )

    REM Load the variable definitions from our temporary file.
    CALL %TEMP%\__refreshEnvironment.bat

    REM Clean up after ourselves.
    DEL /Q %TEMP%\__refreshEnvironment.bat

    ECHO Environment successfully refreshed.

This solution works on my computer (64-bit Windows 10).此解决方案适用于我的计算机(64 位 Windows 10)。 The environment variables get updated.环境变量得到更新。 However, I get the following error:但是,我收到以下错误:

    ERROR: The system was unable to find the specified registry key or value.

Strange.. I get an error, but the variables do get updated.奇怪.. 我收到一个错误,但变量确实得到了更新。


EDIT :编辑:

The environment variables get updated when I call the batch file 'refreshEnv' directly in the terminal window.当我直接在终端窗口中调用批处理文件'refreshEnv'时,环境变量会得到更新。 But it doesn't work when I call it from my Python program:但是当我从我的 Python 程序调用它时它不起作用:

    #################################
    #          PYTHON 3.5           #
    #   -------------------------   #
    # Refresh Environment variables #
    #################################
    def refresh(self):
        p = Popen(self.homeCntr.myState.getProjectFolder() + "\\refreshEnv.bat", cwd=r"{0}".format(str(self.homeCntr.myState.getProjectFolder())))
    ###

Why?为什么? Is it because Popen runs the batch file in another cmd terminal, such that it doesn't affect the current Python process?是不是因为 Popen 在另一个 cmd 终端中运行批处理文件,这样它就不会影响当前的 Python 进程?

On Windows, the initial environment variables are stored in the registry: HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment for system variables and HKEY_CURRENT_USER\\Environment for user variables.在 Windows 上,初始环境变量存储在注册表中: HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment用于系统变量, HKEY_CURRENT_USER\\Environment用于用户变量。

Using the winreg module in Python, you can query these environment variables easily without resorting to external scripts:使用 Python 中的winreg模块,您可以轻松查询这些环境变量,而无需求助于外部脚本:

import winreg
def get_sys_env(name):
    key = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, r"System\CurrentControlSet\Control\Session Manager\Environment")
    return winreg.QueryValueEx(key, name)[0]

def get_user_env(name):
    key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, r"Environment")
    return winreg.QueryValueEx(key, name)[0]

(On Python 2.x, use import _winreg as winreg on the first line instead). (在 Python 2.x 上,改为在第一行使用import _winreg as winreg )。

With this, you can just use get_sys_env("PATH") instead of os.environ["PATH"] any time you want an up-to-date PATH variable.有了这个,您可以在任何需要最新的 PATH 变量时使用get_sys_env("PATH")而不是os.environ["PATH"] This is safer, faster and less complicated than shelling out to an external script.这比使用外部脚本更安全、更快、更简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM