1

私のラボで使用しているバイオインフォマティクス パイプラインを自動化するマネージャーを Perl で作成しようとしています。(関心のある方は、REPET パイプラインを参照してください。) パイプラインには 8 つのステップがあり、そのうちのいくつかは、並行して実行できるサブステップに分割されています。最も注目すべきは、ステップ 3 が 3 つの部分に分割され、ステップ 4 が対応する 3 つの部分に分割されていることです。ステップ 3 の各部分は独立して実行でき、ステップ 3 のコンパニオンが終了するとすぐに、ステップ 4 の対応する部分を開始できます。マネージャーが 3 つの並列スレッドでステップ 3 を起動し、各スレッドについて、ステップ 3 が終了したらすぐにステップ 4 に進むことができるようにしたいと考えています。私が考える最善の方法は、各プロセスの出力を監視することです。各ステップの出力は次のようになります。

START TEdenovo.py (2012-08-23 11:20:10)
version 2.0
project name = dm3_chr2L
project directory = /home/<etc>
beginning of step 1
submitting job(s) with groupid 'dm3_chr2L_TEdenovo_prepareBatches' (2012-08-23 11:20:10)
waiting for 1 job(s) with groupid 'dm3_chr2L_TEdenovo_prepareBatches' (2012-08-23 11:20:10)
execution time per job: n=1 mean=2.995 var=0.000 sd=0.000 min=2.995 med=2.995 max=2.995
step 1 finished successfully
version 2.0
END TEdenovo.py (2012-08-23 11:20:25)

これはステップ 1 の出力ですが、ステップ 3 で「ステップ 3 が正常に終了しました」と出力に表示されたら、安全にステップ 4 に進んでください。一度。基本的に、これは私が望む動作です(疑似コード):

my $log31 = `TEdenovo.py [options] &`;
my $log32 = `TEdenovo.py [options] &`;
my $log33 = `TEdenovo.py [options] &`;

while(1) {
    #start step 41 if $log31 =~ /step 3 finished successfully/;
    #start step 42 if $log32 =~ /step 3 finished successfully/;
    #start step 43 if $log33 =~ /step 3 finished successfully/;
    #monitor logs 41, 42, 43 similarly
    last if #all logs read "finished successfully"
    sleep(5);
}

#move on to step 5

問題は、バックティックでプロセスを呼び出すと、perl がそのプロセスが終了するまで待機することです。私が発見したように、& を使用して何かをバックグラウンド プロセスにスピンし、すぐに続行できる system() とは異なります。私の知る限り、探している効果を得るために system() を使用する良い方法はありません。私はこれを行うことができると思います:

system("TEdenovo.py [options] & > log31.txt");

そして、log31.txt を定期的にポーリングして、「正常に終了しました」が表示されているかどうかを確認しますが、それは不必要に面倒です。

また、ファイルハンドルでプロセスを開こうとしました:

open(my $step3, "TEdenovo.py [options] |");
my @log3;

while(1)
{
    push(@log3, <$step3>);
    last if grep("step 3 finished successfully", @log3);
    sleep(5);
}

...しかし、もう一度、Perl はプロセスが終了するまで (この場合は push() で) 先に進むために待機します。上記を $| で試しました 設定および設定解除の両方。

したがって、私の質問の本質は次のとおりです。実行中のバックグラウンド プロセスの標準出力を perl で取得する方法はありますか?

4

2 に答える 2

1

多分あなたは試すことができます

open(my $step3, "TEdenovo.py [options] |");

while(<$step3>)
{
    last if /step 3 finished successfully/;
}

while(1) の代わりに ?

于 2012-08-23T19:23:24.277 に答える
0

パイプハンドルを使用openして読み取るアプローチは正しいアプローチです。スカラーコンテキストでハンドルから読み取るというナウエルの提案が役に立たない場合でも、バッファリングに苦しんでいる可能性があります。

$|Perl の出力のバッファリング動作を変更しますが、Perl から呼び出される外部プログラムの動作は変更しません。出力をバッファリングしない外部プログラムを使用する必要があります。この場合、-uオプションを pythonに渡すことでこれが可能になると思います。

open(my $step3, "|-", "python -u TEdenovo.py [more options]");
于 2012-08-23T19:28:19.900 に答える