2016-05-11 2 views
0

J'ai un morceau de code python, que j'ai besoin de le convertir en perl, mais malheureusement je ne suis pas bon en perl, donc désolé si la question est simple. Je voudrais vérifier STDOUT et STDERR pour un mot spécifique. Voici le code python:Python code à Perl

p = subprocess.Popen("bmod -b " + beginTime + " " + job_id + "; exit 1;", 
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) 

while p.poll() is None: 
    err = p.stderr.readline().decode('utf_8') 
    out = p.stdout.readline().decode('utf_8') 
    if "changed" in err or "changed" in out: 
     subprocess.Popen("echo rescheduling was successful!", shell=True) 
os._exit(0) 

J'ai lu quelques documentations et fonction open3 peuvent travailler, mais pour une partie de p.poll() Je ne sais pas quoi utiliser.

+3

Il existe plusieurs façons de lire la sortie d'un processus externe en Perl, mais les plus simples sont ['qx()'] (http://perldoc.perl.org/perlop.html#qx%2f_STRING_%2f), [piped 'open'] (http://perldoc.perl.org/perlipc .html # Using-open% 28% 29-pour-IPC), et [Capture :: Tiny] (https://metacpan.org/pod/Capture::Tiny). Pour 'qx' et' open' vous devrez rediriger STDERR puisque vous voulez vérifier STDOUT et STDERR. – ThisSuitIsBlackNot

+2

'open3' +' select' est trop bas. Utilisez 'run3' d'IPC :: Run3 ou' run' d'IPC :: Run. – ikegami

+0

@ikegami Dois-je utiliser quelque chose comme ça pour attendre la sortie? '$ pid = run3' ou' $ pid = open3' 'wait ($ pid, 0)' –

Répondre

3

La réponse dépend s'il est important d'imprimer le message "rescheduling was successful!" immédiatement après la ligne a été imprimée à partir bmod (quand bmod est encore en cours) ou s'il suffit d'imprimer la ligne après bmod a quitté.

Le dernier cas est très simple à réaliser en Perl, par exemple:

my $out = qx/bmod -b $beginTime $job_id 2>&1/; 
say "rescheduling was successful!" if $out =~ /changed/; 

En ce qui concerne le premier cas, si vous avez besoin d'imprimer le message, la première note immédiatement (avant même bmod a quitté) que votre script Python ne fonctionne probablement pas correctement. Les lignes p.stderr.readline() bloqueront le script jusqu'à ce qu'une ligne soit prête à être lue depuis p.stderr, de même p.stdout.readline() bloquera le script jusqu'à ce qu'une ligne soit prête à être lue depuis p.stdout. Donc, si bmod ne s'imprime que sur stdout et que rien ne va à stderr, le script se bloquera au premier appel à p.stderr.readline() et ne retournera que si bmod se termine.

Je ne suis pas sûr de savoir comment le faire correctement en Python, mais en Perl, vous pouvez utiliser IPC::Open3 combiné avec IO::Select. Voir par exemple: Perl select return “bad file descriptor” error

A noter également: Une solution plus simple en Perl peut être achived en utilisant open si stderr et stdout sont fusionnés:

my $pid = open (my $fh, '-|', "bmod -b $beginTime $job_id 2>&1") or die "Could not run command: $!"; 
while (my $line = <$fh>) { 
    print $line if $line =~ /changed/; 
} 
close $fh;