2017-12-20 21 views
2

現在、私のC++プログラムからpythonで書かれたファイルをpstreamライブラリ(http://pstreams.sourceforge.net/)で起動しようとしています。私のコードは次のようになります。C++のpythonプログラムからstderrを取得する

QStringList res; 
QStringList resErrors; 

// run a process and create a streambuf that reads its stdout and stderr 
redi::pstream proc(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr); 

std::string line; 
// read child's stdout 
while (std::getline(proc.out(), line)) 
    res.append(QString::fromStdString(line)); 
// read child's stderr 
while (std::getline(proc.err(), line)) 
    resErrors.append(QString::fromStdString(line)); 

通常、正しく生成され、エラーメッセージはpstreamコンストラクタに入力されたコマンドから出力されます。しかし、トレースバックを発生させるpythonファイルを実行しようとすると、(stdoutまたはstderrに)出力がありません。例えば

、このPythonのファイル:

#!/usr/bin/env python 

test = 5/0 
print "test" 

意志stdoutとstderrで何でノープリント "テスト"。私は、端末でそれを実行した場合でも、私が正しくなった:私は、同じコマンドを使用し、両方の場合

Traceback (most recent call last): 
    File "test.py", line 3, in <module> 
     test = 5/0 
    ZeroDivisionError: integer division or modulo by zero 

:「Pythonのtest.py」

私はそのを印刷するのpythonに指示する必要があります推測しますstderrへのトレースバック?しかし、なぜそれがサブプロセスで行われていないのですか?あるいは、それは図書館のバグでしょうか?

私が念頭に置いている別の可能性は、stdoutとstderrをあまりにも早く読み込み、Pythonに書き込む時間がなかったことです。しかし、私はそれを読む前にスリープ機能を追加しようとしましたが、何の効果もありません。

+0

stdoutを読み取ると、stderrによってデッドロックが発生する可能性があります。別々のスレッドでそれらを読まなければなりません/それらを読むために非ブロッキングな方法を見つけなければなりません。 –

+0

さて、私はそれを試してみましょう。しかし、実際には、2つの「条件」が無効になるため、デッドロックは発生しません。この場合、出力がまったくないようなものです – Kryx

答えて

1

問題は、@ Jean-FrançoisFabreの回答の一部で効果的に解決されます。私は私のQStringListsにすべての出力を持って、これにより

const redi::pstreams::pmode mode = redi::pstreams::pstdout|redi::pstreams::pstderr; 
redi::ipstream child(cmd, mode); 
char buf[1024]; 
std::streamsize n; 
bool finished[2] = { false, false }; 
while (!finished[0] || !finished[1]) 
{ 
    if (!finished[0]) 
    { 
     while ((n = child.err().readsome(buf, sizeof(buf))) > 0) { 
      std::string ret(buf, n); 
      resErrors.append(QString::fromStdString(ret)); 
     } 
     if (child.eof()) 
     { 
      finished[0] = true; 
      if (!finished[1]) 
       child.clear(); 
     } 
    } 

    if (!finished[1]) 
    { 
     while ((n = child.out().readsome(buf, sizeof(buf))) > 0) { 
      std::string out(buf, n); 
      res.append(QString::fromStdString(out)); 
     } 
     if (child.eof()) 
     { 
      finished[1] = true; 
      if (!finished[0]) 
       child.clear(); 
     } 
    } 
} 
res = res.join("").split("\n"); 
resErrors = resErrors.join("").split("\n"); 
res.removeLast(); 
resErrors.removeLast(); 

私はpstreamsはブロックせずにパイプに読み込むための方法を提供し、私は(ライブラリのドキュメントで見つかった)そのコードを再利用することに気づきました!