使用'默认'启动新的子流程环境变量

时间:2014-05-19 00:35:36

标签: python environment-variables

我正在编写一个构建脚本来解析依赖的共享库(及其共享库等)。普通的PATH环境变量中不存在这些共享库。

为了使构建过程起作用(编译器找到这些库),PATH已被更改为包含这些库的目录。

因此构建过程是:

Loader脚本(更改PATH) - >基于Python的构建脚本 - >配置 - >构建 - >解决依赖关系 - >安装。

Python实例从其父shell继承了一个已更改的PATH变量。

在Python中,我正在尝试获取默认的PATH(不是从其父shell继承的那个)。

这个想法:

解决'默认'PATH变量的想法是以某种方式“发出信号”操作系统启动一个新进程(运行打印PATH的脚本),但这个过程是一个孩子的当前的Python进程(并且可能不会继承其修改的环境变量)。

尝试实施:

import os
import sys

print os.environ["PATH"]
print "---"
os.spawnl(os.P_WAIT, sys.executable, "python", "-c \"import os;print(os.environ['PATH']);\"")

os.spawn似乎使用与调用它的Python进程相同的环境变量。我也用subprocess.POpen尝试过这种方法,但没有成功。

这种方法可以实施吗?如果没有,什么是替代方法(假设加载器脚本和整个过程不能改变)?

我目前正在使用Windows,但构建脚本是跨平台的。

修改

跨平台约束似乎过于严格。现在可以考虑相同概念的不同实现。

例如,使用this回答中的代码,Windows注册表可用于获取“默认”系统PATH变量。

try:
    import _winreg as winreg
except ImportError:
    try:
        import winreg
    except ImportError:
        winreg = None

def env_keys(user=True):
    if user:
        root = winreg.HKEY_CURRENT_USER
        subkey = "Environment"
    else:
        root = winreg.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 = winreg.OpenKey(root, subkey, 0, winreg.KEY_READ)
    try:
        value, _ = winreg.QueryValueEx(key, name)
    except WindowsError:
        return ""
    value = winreg.ExpandEnvironmentStrings(value)
    return value

print get_env("PATH", False)

需要一致的* nix方法。

2 个答案:

答案 0 :(得分:2)

使用subprocess.Popen,您可以为子进程提供使用环境:

default_path = os.environ['PATH'] # save the default path before changing it
os.environ['PATH'] = # whatever you want
child_env = os.environ.copy()
child_env['PATH'] = default_path
# change env
subprocess.Popen(..., env=child_env)

documentation表示将使用提供的环境而不是从父级继承它:

  

如果env不是None,则它必须是定义环境的映射   新过程的变量;这些用于代替继承   当前进程的环境,这是默认行为。

答案 1 :(得分:0)

默认'你的意思是什么? PATH的价值?登录时的值是多少?某些系统范围的默认值?加载程序脚本在更改之前启动的值?

最简单的方法是使用您自己的一个来装入加载器脚本(如果您真的无法更改它),将PATH的当前值保存在某些其他环境变量(如OLD_PATH)中。然后你可以使用类似的东西:

os.spawnle( ... , {'PATH' : os.environ['OLD_PATH']})

或者你可以将shell作为登录或至少交互式shell生成,并在调用python之前让它来源用户的.bashrc(或其他启动)。

**更新**用于Windows,并假设您只想获取PATH:

Spawn CMD.EXE,让它执行命令' echo%PATH%'