Я перевожу bash-скрипт для выполнения вычислений и выполнения некоторой постобработки в Python и столкнулся с трудностями, когда попытался передать вывод программы в sed. Проблема заключается в переводе такого рода конвейера:
#!/bin/bash
echo -e "whatever\n1 2" | ./a.out | sed -e 's/.* //'
где исполняемый файл компилируется из:
#include <iostream>
#include <string>
#define FLUSH true
int main(int argc, char** argv) {
std::string filename;
int param1, param2;
std::cout << "Input name of file: " << std::flush;
std::cin >> filename;
std::cout << "Enter params, separated by a space: " << std::flush;
std::cin >> param1 >> param2;
for(int i = 0; i < 400; i++) {
std::cout << "Result " << i << ": " << i*param1+i*i*param2/(param1+i) << "\n";
if(FLUSH) {
std::cout << std::flush;
}
}
}
Я пробую следующее
import subprocess
compute = subprocess.Popen(['./a.out'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
strip = subprocess.Popen(['sed','-e', 's/.* //'], stdin=compute.stdout, stdout=subprocess.PIPE)
out, err = compute.communicate('filename.csv\n1 2')
print out
Но вместо получения списка необработанных выходных данных, как и ожидалось, я получаю случайную подпоследовательность строк из выходных данных программы, например:
Result 0: 0
Result 2: 4
Result 3: 7
Result 4: 10
Result 5: 13
Result 6: 16
Result 14: 40
...
Result 392: 1174
Result 396: 1186
Result 399: 1195
Я не использую случайный, чтобы означать произвольный: результат варьируется от одного выполнения сценария к следующему. Из-за этого я предполагаю, что проблема связана с синхронизацией сбросов выходного буфера, так что sed не получает выходные строки по одной - поэтому я экспериментировал с переменным сбросом буфера после каждой строки. Однако это не решило проблему, и ни один из примеров, которые я нахожу в Интернете об использовании подпроцесса для такого рода задач, не упоминал эту проблему. Возможно, есть какой-то способ убедиться, что вторая команда не выполняется до тех пор, пока не завершится первая, или обработать строки по одной за раз?
Вторая проблема заключается в том, почему сценарий sed не выполняет желаемого удаления подстроки в моем примере с игрушкой; он отлично работает в реальном сценарии, который я пишу, хотя случайные строки не передаются по всему конвейеру.
Для ясности, желаемый результат будет выглядеть так:
0
2
4
7
10
13
16
19
...
1183
1186
1189
1192
1195