如何在 Python 中读出 *new* OS 环境变量?

Posted

技术标签:

【中文标题】如何在 Python 中读出 *new* OS 环境变量?【英文标题】:How to read out *new* OS environment variables in Python? 【发布时间】:2016-11-27 11:14:04 【问题描述】:

在 Python 中读取操作系统环境变量是小菜一碟。尝试以下三行代码,在 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;
        ...

现在对'PATH' 变量做一个小改动。您可以在以下位置找到它们:

控制面板>>系统和安全>>系统>>高级系统设置>> 环境变量

如果您在 Python 中运行相同的代码,更改是不可见的!您必须关闭启动 Python 会话的终端。当您重新启动它并再次运行代码时,更改将可见。

有没有办法立即查看更改 - 无需关闭 python?这对于我正在构建的应用程序很重要。

非常感谢你:-)


编辑:

Martijn Pieters 向我展示了以下链接: Is there a command to refresh environment variables from the command prompt in Windows?

该链接中提到了许多选项。我选择了以下的(因为它只是一个批处理文件,没有额外的依赖):

            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://***.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.

此解决方案适用于我的计算机(64 位 Windows 10)。环境变量得到更新。但是,我收到以下错误:

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

奇怪..我得到一个错误,但变量确实得到了更新。


编辑:

当我直接在终端窗口中调用批处理文件'refreshEnv' 时,环境变量会得到更新。但是当我从我的 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())))
    ###

为什么?是不是因为Popen在另一个cmd终端运行批处理文件,所以不影响当前的Python进程?

【问题讨论】:

很快:你不能。环境变量是在启动时为进程设置的,并且不会更新。这不仅限于 Python。 如果这是 Linux,这将是 Is there a way to change another process's environment variables? 的欺骗,但同样的限制适用于 Windows。 密切相关,如果不是直接欺骗,因为它解释了环境变量和进程内存:Is there a command to refresh environment variables from the command prompt in Windows? 哇,谢谢 Martijn!这些链接真的很有帮助:-) 嗨@MartijnPieters,感谢您的链接,我找到了一种解决方案。但是,我仍然收到一条错误消息。你知道为什么吗? (我已经用详细信息更新了我的问题:-) 【参考方案1】:

在 Windows 上,初始环境变量存储在注册表中:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment 用于系统变量,HKEY_CURRENT_USER\Environment 用于用户变量。

使用 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]

(在 Python 2.x 上,请在第一行使用 import _winreg as winreg)。

有了这个,您可以在任何时候使用get_sys_env("PATH") 而不是os.environ["PATH"] 来获取最新的 PATH 变量。这比使用外部脚本更安全、更快、更简单。

【讨论】:

Nneonneo,你真是个天才! 我明天会尝试你的解决方案,并让你知道结果。谢谢你! 我刚试了一下。谢谢@nneonneo!效果很好! 我们如何为 Linux 做到这一点? @Sakalya 这是一个非常不同的问题,应该得到更多的答案而不是评论。您应该在此处发布并链接。

以上是关于如何在 Python 中读出 *new* OS 环境变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何解决Python中os.path.join的路径拼接问题

python3-os模块

python如何读取文件的内容

Python的一些模块的使用

49. Python 发邮件

如何在 Mac OS 上用 C++ 实现命名管道?