Azade f Azade f - 5 months ago 7
Perl Question

Python code to Perl

I have a piece of python code, that I need to convert it to perl, but unfortunately I am not good in perl, so sorry if the question is simple.
I would like to check STDOUT and STDERR for a specific word. Here is the python code:

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)

I read some documentations and open3 function may work here, but for p.poll() part I am not sure what to use.


The answer depends on if it is important to print the message "rescheduling was successful!" immediately after a the line was printed from bmod (when bmod is still running) or if it is sufficient to print the line after bmod has exited.

The last case is a very simple to achieve in Perl, for example:

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

Regarding the first case, if you need to print the message immediately (even before bmod has exited), first note that your Python script is probably not working correctly. The lines p.stderr.readline() will block the script until a line is ready to be read from p.stderr, similarly p.stdout.readline() will block the script until a line is ready to be read from p.stdout. So if bmod only prints to stdout and nothing goes to stderr, the script will hang at the first call to p.stderr.readline() and only return when bmod exits.

I am not sure how to do this correctly in Python, but in Perl you can use IPC::Open3 combined with IO::Select. See for example: Perl select return “bad file descriptor” error

Also note: A simpler solution in Perl can be achived using open if stderr and stdout are merged:

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;