如何从子流程获取环境?

2024-09-25 04:17:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我想通过python程序调用一个进程,但是这个进程需要一些由另一个进程设置的特定环境变量。如何让第一个流程环境变量传递给第二个流程环境变量?

程序就是这样的:

import subprocess

subprocess.call(['proc1']) # this set env. variables for proc2
subprocess.call(['proc2']) # this must have env. variables set by proc1 to work

但是to进程不共享相同的环境。注意,这些程序不是我的(第一个是大而难看的.bat文件,第二个是专有软件),所以我不能修改它们(好吧,我可以从.bat中提取所有我需要的东西,但它非常好斗)。

注意:我使用的是Windows,但我更喜欢跨平台的解决方案(但我的问题不会发生在类似Unix的系统上…)


Tags: toimport程序env进程环境变量流程variables
3条回答

下面是一个示例,说明如何在不创建包装脚本的情况下从批处理或cmd文件中提取环境变量。享受吧。

from __future__ import print_function
import sys
import subprocess
import itertools

def validate_pair(ob):
    try:
        if not (len(ob) == 2):
            print("Unexpected result:", ob, file=sys.stderr)
            raise ValueError
    except:
        return False
    return True

def consume(iter):
    try:
        while True: next(iter)
    except StopIteration:
        pass

def get_environment_from_batch_command(env_cmd, initial=None):
    """
    Take a command (either a single command or list of arguments)
    and return the environment created after running that command.
    Note that if the command must be a batch file or .cmd file, or the
    changes to the environment will not be captured.

    If initial is supplied, it is used as the initial environment passed
    to the child process.
    """
    if not isinstance(env_cmd, (list, tuple)):
        env_cmd = [env_cmd]
    # construct the command that will alter the environment
    env_cmd = subprocess.list2cmdline(env_cmd)
    # create a tag so we can tell in the output when the proc is done
    tag = 'Done running command'
    # construct a cmd.exe command to do accomplish this
    cmd = 'cmd.exe /s /c "{env_cmd} && echo "{tag}" && set"'.format(**vars())
    # launch the process
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=initial)
    # parse the output sent to stdout
    lines = proc.stdout
    # consume whatever output occurs until the tag is reached
    consume(itertools.takewhile(lambda l: tag not in l, lines))
    # define a way to handle each KEY=VALUE line
    handle_line = lambda l: l.rstrip().split('=',1)
    # parse key/values into pairs
    pairs = map(handle_line, lines)
    # make sure the pairs are valid
    valid_pairs = filter(validate_pair, pairs)
    # construct a dictionary of the pairs
    result = dict(valid_pairs)
    # let the process finish
    proc.communicate()
    return result

因此,要回答您的问题,您需要创建一个.py文件,该文件执行以下操作:

env = get_environment_from_batch_command('proc1')
subprocess.Popen('proc2', env=env)

正如您所说,进程不共享环境,因此您字面上的要求是不可能的,不仅在Python中,而且在任何编程语言中都是不可能的。

您可以将环境变量放入文件或管道中,然后

  • 让父进程读取它们,并在创建proc2之前将它们传递给proc2,或者
  • 让proc2读取它们,并在本地设置它们

后者需要proc2的合作;前者需要在proc2启动之前知道变量。

既然你显然是在Windows里,你需要Windows的答案。

创建包装批处理文件,例如“run_program.bat”,并运行两个程序:

@echo off
call proc1.bat
proc2

脚本将运行并设置其环境变量。两个脚本在同一个解释器(cmd.exe实例)中运行,因此在执行prog2时,变量prog1.bat sets将被设置为

不是很漂亮,但会有用的。

(Unix用户,可以在bash脚本中执行相同的操作:“source file.sh”。)

相关问题 更多 >