2009-07-31 20 views
14

私はpythonプログラムを介してプロセスを呼び出したいが、このプロセスは別のプロセスによって設定された特定の環境変数を必要とする。どのようにして最初のプロセス環境変数を取得し、2番目のプロセス環境変数に渡すことができますか?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ファイル、もう1つは独自のソフトです)ので、私はそれらを変更することはできません(OK、私は必要なすべてを.batから抽出できますが、 )。

NB:私はWindowsを使用していますが、私はクロスプラットフォームソリューションを好む(しかし、私の問題は、Unixライクに起こりません...)

+0

の.batファイル:

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ファイルを作成しますか?あなたがWindowsで走っているなら、あなたは本当にはっきりと言うべきです。 –

答えて

2

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

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

@echo off 
call proc1.bat 
proc2 

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

とてもかわいいですが、うまくいきます。

(Unixの人々は、あなたはbashスクリプトで同じことを行うことができます。「ソースfile.sh」)

+0

私は特に 'sourch blahを使って回避しようとしています。 now_do_second_thing' – nmz787

4

をあなたが言うように、プロセスは共有しません環境 - あなたが文字通り尋ねることは、Pythonだけでなくプログラミング言語でも可能ではありません。あなたは行うファイル内の環境変数を置くことである、またはパイプで、かつ

  • は、親プロセスはそれらを読んで持っている、とPROC2が作成される前に、PROC2するためにそれらを渡すのいずれかすることができますどのような

    または

  • はそれらを読んで、そして

PROC2からの協力が必要になり、後者をローカルに設定PROC2持っています。前者はproc2が起動する前に変数がわかっていることを要求します。

+0

Linuxの場合、rootであれば/ proc//environをチェックして解析することはできません。 "不可能"ではありません。 – 0x6adb015

+0

@ 0x6abd015:しかし、これはOPが尋ねるものではなく、proc2がproc1の環境(procファイルシステムで何ができるか)を知りたくないのですが、proc1がproc2の環境を設定*私はまだこれは不可能だと主張する。 –

0

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

+0

これは質問に答えません。たとえばENV varsの競合を必要とするプログラムがある場合は、これに反対する理由もあります。 – nmz787

0

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

0

The Python standard module multiprocessingには、picklesableオブジェクトをプロセスに渡すことができるQueuesシステムがあります。また、プロセスはos.pipeを使用してメッセージ(ピクルされたオブジェクト)を交換することもできます。リソース(データベース接続など)とハンドル(例:ファイルハンドル)は、ピクルできません。

あなたは、このリンクは面白いかもしれません: Communication between processes with multiprocessing

も言及する価値がマルチプロセッシングに関するPyMOTw:私のスペル multiprocessing Basics

は申し訳ありません

23

は、ここでは、バッチまたはCMDファイルから環境変数を抽出する方法の例です作成することなく、ラッパースクリプト。楽しい。

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

編集は、書かれた実装が非ASCIIコードページをサポートしていないことを示唆しました。その場合、推奨される修正は、cmdの構築に '{env_cmd} 'の前に' chcp 65001> NULL && 'を置くことでした。 –

+1

ここに、この機能の最新バージョンが掲載されています。https://github.com/PySide/pyside2-setup/blob/master/utils.py#L379 –

+0

OPがリクエストしたので、これはクロスプラットフォームではありません。 – nmz787

関連する問題