19 python windows subprocess environment-variables popen
我想通过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
但是进程不共享相同的环境.请注意,这些程序不是我的(第一个是大而丑陋的.bat文件,第二个是专有软件)所以我无法修改它们(好吧,我可以从.bat中提取我需要的所有东西,但它非常简洁).
注意:我使用的是Windows,但我更喜欢跨平台的解决方案(但我的问题不会发生在类似Unix的问题上......)
Jas*_*mbs 27
下面是如何在不创建包装器脚本的情况下从批处理或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启动之前变量已知.
由于您显然使用的是 Windows,因此您需要 Windows 答案。
创建一个包装批处理文件,例如 “run_program.bat”,并运行这两个程序:
@echo off
call proc1.bat
proc2
该脚本将运行并设置其环境变量。两个脚本都在同一个解释器(cmd.exe 实例)中运行,因此prog2 执行时将设置变量 prog1.bat 设置。
不是很漂亮,但它会起作用。
(Unix 用户,您可以在 bash 脚本中执行相同的操作:“source file.sh”。)