2017-12-20 3 views
2

현재 C++ 프로그램에서 파이썬으로 작성된 파일을 pstream 라이브러리 (http://pstreams.sourceforge.net/)로 시작하려고합니다. 내 코드는 다음과 같습니다 :C++ 하나의 파이썬 프로그램에서 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에 있음). 예를 들어

이 파이썬 파일 :

#!/usr/bin/env python 

test = 5/0 
print "test" 

것이다 표준 출력과 표준 에러에 아무것도 없음 인쇄 "테스트". 내가 터미널에서 그것을 실행하면, 나는 제대로 가지고 :

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

을 나는 같은 명령을 사용하는 두 경우 : 나는 인쇄 할 파이썬에 알려줄 필요가 생각 "파이썬 test.py"

을 그 역 추적으로의 추적? 하지만 하위 프로세스에서이 작업이 수행되지 않는 이유는 무엇입니까? 아니면 도서관의 버그 일 수 있습니까?

내가 생각할 수있는 또 다른 가능성은 stdout과 stderr를 너무 일찍 읽고 파이썬에 쓸 시간이 없다는 것입니다. 그러나 어떤 효과도없이 그것을 읽기 전에 수면 기능을 추가하려고했습니다.

+0

stdout을 읽은 후 stderr이 교착 상태가 될 수 있습니다. 당신은 그것들을 별도의 쓰레드로 읽어야 만한다. –

+0

좋아, 그걸 시도해 볼게. 하지만 실제로 두 조건이 무효화되는 동안 교착 상태가 발생하지 않습니다. 이 경우 출력이 전혀없는 것과 같습니다. – Kryx

답변

1

좋아,이 문제는 @ Jean-François Fabre의 대답의 일부로 효과적으로 해결됩니다. 내 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은 차단하지 않고 파이프에서 읽을 수있는 방법을 제공, 그래서 (라이브러리의 문서에서 발견) 그 코드를 재사용 할 것으로 나타났습니다 !