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

Python 使用'启动新的子流程;默认值';环境变量,python,environment-variables,Python,Environment Variables,我正在编写一个构建脚本来解析依赖共享库(及其共享库等)。这些共享库不存在于正常的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_CUR

我正在编写一个构建脚本来解析依赖共享库(及其共享库等)。这些共享库不存在于正常的
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)
为了使构建过程正常工作(为了让编译器找到这些库),
路径已更改为包含这些库的目录

因此,构建过程是:

加载程序脚本(更改路径)->基于Python的生成脚本->配置->生成->解析依赖项->安装

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

在Python中,我试图获取默认的
路径(不是从其父shell继承的路径)

这个想法:

解析“默认”路径变量的想法是以某种方式“通知”操作系统启动一个新进程(运行打印路径的脚本),但该进程不是当前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,但构建脚本将是跨平台的

编辑:

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

例如,使用answer中的代码,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使用一致的方法。

路径的“默认”值到底是什么意思?您登录时它的值是多少?一些系统范围的默认值?加载程序脚本在进行更改之前开始的值

最简单的方法是使用自己的加载程序脚本包装加载程序脚本(如果您确实无法更改它),该脚本将PATH的当前值保存在其他环境变量(如OLD_PATH)中。然后,您可以使用以下内容:

os.spawnle( ... , {'PATH' : os.environ['OLD_PATH']})
或者,您可以生成一个shell作为登录名,或者至少是交互式shell,并让它在调用python之前为用户的.bashrc(或其他启动)提供源代码

**为windows更新**,假设您只想获取路径:


Spawn CMD.EXE,让它使用
subprocess.Popen执行命令“echo%PATH%”

,您可以为子进程提供一个使用环境:

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)
声明将使用提供的环境,而不是从父环境继承它:

如果env不是None,则它必须是定义环境的映射 新流程的变量;它们被使用而不是继承 当前进程的环境,这是默认行为


此实例中的默认值被认为是加载程序脚本之前的环境。我不希望将环境变量传递给子流程;我正在寻找返回默认环境的子流程。这是在Windows上,尽管构建脚本是跨平台的。我知道您希望生成的进程告诉您它的环境是什么。然后我回答的第二部分来了:生成一个运行CMD.EXE(windows)或bash(linux)的进程,让它告诉你它的路径是什么。更新这些细节的答案。我考虑过了。是否有方法向操作系统发出启动新进程的“信号”(但不是作为当前Python进程的子进程)?Python构建脚本不会更改
PATH
变量,因为还有其他非Python工具需要修改
PATH
。因此,
路径
的更改必须发生在加载脚本中。我编辑了我的答案,以反映我认为您在尝试做什么,但我真的不确定我是否完全理解这个问题。等等,加载脚本不是用Python编写的吗?在调用Python脚本之前,您不能让加载程序脚本保存环境变量的默认路径吗?我为任何混淆道歉。加载程序脚本是一个
.bat
文件,必须保持这种状态。我编辑了这个问题。您知道一种向操作系统发出“信号”以启动一个不是Python子进程的新进程的方法吗?Python脚本是可移植的,但加载程序脚本是特定于平台的。我不想在构建脚本中对备份路径进行任何引用。