Код Python для Perl

У меня есть кусок кода Python, который мне нужно преобразовать в Perl, но, к сожалению, я не очень хорош в Perl, поэтому извините, если вопрос прост. Я хотел бы проверить STDOUT и STDERR для конкретного слова. Вот код Python:

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)

Я прочитал некоторые документы, и здесь может работать функция open3, но для части p.poll() я не уверен, что использовать.

1 ответ

Решение

Ответ зависит от того, важно ли напечатать сообщение "rescheduling was successful!" сразу после того, как строка была напечатана из bmod (когда bmod все еще работает) или если достаточно напечатать строку после bmod вышел.

Последний случай очень прост в Perl, например:

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

Что касается первого случая, если вам нужно распечатать сообщение немедленно (даже до bmod вышел), сначала обратите внимание, что ваш скрипт на Python, вероятно, работает неправильно. Линии p.stderr.readline() будет блокировать скрипт, пока строка не будет готова для чтения из p.stderr, так же p.stdout.readline() будет блокировать скрипт, пока строка не будет готова для чтения из p.stdout, Так что если bmod печатает только stdout и ничего не идет stderr скрипт будет зависать при первом вызове p.stderr.readline() и возвращаться только тогда, когда bmod выходы.

Я не уверен, как это сделать правильно в Python, но в Perl вы можете использовать IPC::Open3 в сочетании с IO::Select, Смотрите, например: Perl select return error "неверный дескриптор файла"

Также обратите внимание: более простое решение в Perl может быть достигнуто с помощью open если stderr а также stdout объединены:

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;
Другие вопросы по тегам