25

Python プログラムを介してプロセスを呼び出したいのですが、このプロセスには、別のプロセスによって設定された特定の環境変数が必要です。最初のプロセス環境変数を取得して 2 番目に渡すにはどうすればよいですか?

プログラムは次のようになります。

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 ファイルで、2 番目のファイルは独自のソフトです) ので、変更することはできません (わかりました。.bat から必要なものをすべて抽出することはできますが、非常に面倒です)。 )。

注意: 私は Windows を使用していますが、クロスプラットフォーム ソリューションを好みます (ただし、Unix ライクでは問題は発生しません ...)

4

7 に答える 7

30

ラッパー スクリプトを作成せずに、バッチ ファイルまたは 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)
于 2010-02-06T18:53:31.247 に答える
5

あなたが言うように、プロセスは環境を共有しません。したがって、Python だけでなく、どのプログラミング言語でも、文字通り求めることは不可能です。

できることは、環境変数をファイルまたはパイプに入れることです。

  • 親プロセスにそれらを読み取らせ、proc2 を作成する前にそれらを proc2 に渡します。または
  • proc2にそれらを読み取らせ、ローカルに設定します

後者は proc2 からの協力が必要です。前者では、proc2 が開始される前に変数が認識される必要があります。

于 2009-07-31T19:48:31.650 に答える
2

あなたは明らかにWindowsを使用しているので、Windowsの答えが必要です。

ラッパーバッチファイルを作成します。「run_program.bat」、および両方のプログラムを実行します。

@echo off
call proc1.bat
proc2

スクリプトが実行され、環境変数が設定されます。両方のスクリプトは同じインタープリター(cmd.exeインスタンス)で実行されるため、prog2の実行時に変数prog1.batが設定れます。

それほどきれいではありませんが、動作します。

(Unixの人々、bashスクリプトで同じことを行うことができます: "sourcefile.sh"。)

于 2009-07-31T22:31:09.593 に答える
1

Python 標準モジュール multiprocessingには、プロセスを介して渡されるピクル可能なオブジェクトを渡すことができるキュー システムがあります。また、プロセスは os.pipe を使用してメッセージ (pickled オブジェクト) を交換できます。リソース (例: データベース接続) とハンドル (例: ファイルハンドル) は pickle できないことに注意してください。

このリンクは興味深いかもしれません: マルチプロセッシングを使用したプロセス間の通信

また、言及する価値のあるマルチプロセッシングに関する PyMOTw : マルチプロセッシングの基本

私のつづりでごめんなさい

于 2009-07-31T20:44:51.227 に答える
0

2 つのことが頭に浮かびます: (1) プロセスを何らかの方法で同じプロセスに結合することにより、プロセスに同じ環境を共有させるか、(2) 最初のプロセスに関連する環境変数を含む出力を生成させ、Python がそれを読み取ることができるようにします。 2 番目のプロセスの環境を構築します。あなたが望んでいるように、サブプロセスから環境を取得する方法はないと思います(100%確信はありませんが)。

于 2009-07-31T19:49:12.710 に答える
-1

環境は親プロセスから継承されます。サブプロセス (子プロセス) ではなく、メイン スクリプトで必要な環境を設定します。

于 2009-07-31T19:49:06.580 に答える