2017-03-23 10 views
1

コマンドライン引数を受け入れるPythonスクリプトjob.pyがあります。このスクリプトは、Pythonパッケージsubprocessを使用していくつかの外部プログラムを実行します。スクリプトと外部プログラムの両方が順番です(つまり、MPI、openMPなどはありません)。私はこのスクリプトを毎回異なるコマンドライン引数で4回実行したいと思います。私のプロセッサは4つのコアを持っているので、私は同時に4つのインスタンスをすべて実行したいと思います。私は4つの端末を開いて、別々の端末でスクリプトの各インスタンスを実行すると、それは完全に動作し、私は欲しいものを正確に取得します。subprocess.callを使用する同じPythonスクリプトの複数のインスタンスを実行する方法

ここでは、1つの端末から1つのコマンドですべてを実行できるように、4つのインスタンスを簡単に起動するようにしたいと考えています。このため私はbashスクリプトを使用していますbatch.sh

これは機能しません。 subprocessがここでの犯人であることが判明しました。だから私はそれを参照してくださいどのように、私はバックグラウンドでjob.pyを実行しようとしていますということです

[1]+ Stopped     python job.py 4 0 

job.py自体はバックグラウンドで何かを実行しようとします:それはsubprocess.callに当たるまで、すべてのPythonコードは、私が取得された後、完全に実行されますvia subprocess。これは明らかに私が理解できない理由では機能しません。

複数の端末を必要とせずにjob.pyを複数回実行する方法はありますか?推薦

EDIT#1

私はmultiprocessingthreadthreadingパッケージを試してみました。最良のケースでは、1つのインスタンスが正しく実行されました。私は動作する醜い回避策を試しました。私は新しいターミナル内の各インスタンスを起動するbashスクリプトを作った:

konsole -e python job.py 4 0 
konsole -e python job.py 4 1 
konsole -e python job.py 4 2 
konsole -e python job.py 4 3 

ここでEDIT#2

subprocess.call(注:subprocessspとしてインポートされた)を使用して実際の関数です。

def run_case(path): 
    case = path['case'] 
    os.chdir(case) 
    cmd = '{foam}; {solver} >log.{solver} 2>&1'.format(foam=CONFIG['FOAM'], 
                 solver=CONFIG['SOLVER']) 
    sp.call(['/bin/bash', '-i', '-c', cmd]) 

私は空白のスポットに記入してみましょう:

  • CONFIGは、グローバルに定義された辞書です。
  • CONFIG['FOAM'] = 'of40'これは私が実行しているバイナリに属する​​ファイルのソースに使用される.bashrcのエイリアスです。
  • CONFIG['SOLVER'] = 'simpleFoam'これは私が実行しているバイナリです。

EDIT#3

私は最終的にこの

def run_case(): 
    case = CONFIG['PATH']['case'] 
    os.chdir(case) 
    cmd = 'source {foam}; {solver} >log.simpleFoam 2>&1'.format(foam=CONFIG['FOAM'], 
                   solver=CONFIG['SOLVER']) 
    sp.call([cmd], shell=True, executable='/bin/bash') 

ソリューションで動作するようにそれを得た代わりに、実際のコマンドラインで/bin/bashを含むの両方shell=Trueexecutable='/bin/bash'設定しましたシェルに渡します。注:foamは、エイリアスの代わりにファイルへのパスになりました。

+0

'停止 'は単に' job.py'のインスタンスが終了したことを意味します。 – Apalala

+3

これは 'subprocess'モジュールとは関係がありません。私は実行しているプログラムが 'stdout'に書きたいと思っていますし、バックグラウンドに置いているので' SIGTTOU'を受け取るので、あなたの制御端末にアクセスすることはできません。これは標準的な動作です。プログラムからの出力( 'stdout = subprocess.PIPE'と' stderr = subprocess.PIPE')をキャプチャすることはできますが、プログラムの出力を正しく処理する必要があります( 'subprocess.Popen'と' communicate'メソッド)。 – larsks

+0

異なるコアにアクセスするには、スレッドを使用する必要があります。 https://www.tutorialspoint.com/python/python_multithreading.htm – Tobey

答えて

2

あなたは、Python内から並列化することができます

import multiprocessing 
import subprocess 

def run_job(spec): 
    ... 
    if spec ...: 
     subprocess.call(...) 

def run_all_jobs(specs): 
    pool = multiprocessing.Pool() 
    pool.map(run_job, specs) 

それはあなたが並列化をデバッグ/ログ/監視させるという利点を有しています。

+0

私はこれを試しましたが、ジョブの1つだけを実行します。プール内の他のものを実行するには、端末に 'fg'と入力する必要があります。 'subprocess.call'より前のものはすべて期待通りに動作するので、' subprocess.call'はロック動作をしています。すべての 'subprocess.call'をコメントアウトすると、完了するまですべてのジョブが実行されます(自然に役立つことはありません)。 – mtgoncalves

+0

'subprocess.call()で何を呼びますか? 'shell = True'を使っていますか? – Apalala

+0

'shell'を' True'と 'False'に設定して試しました。 'subprocess.call'を使う関数については、OPの** EDIT#2 **を参照してください。 – mtgoncalves

関連する問題