2012-02-24 1 views
0

python 스크립트에서 STDIN을 읽는 데 이상한 문제가 있습니다.STDIN에서 올바르게 읽을 수 없습니다

여기가 나의 사용 사례입니다. rsyslog가 출력 모듈로 구성되어있어 rsyslog가 로그 메시지를 파이썬 스크립트로 파이프 할 수 있습니다.

내 파이썬 스크립트는 정말 간단하다 :

#! /usr/bin/env python 
# -*- coding: utf-8 -*- 
import sys 

fd = open('/tmp/testrsyslogomoutput.txt', 'a') 
fd.write("Receiving log message : \n%s\n" % ('-'.join(sys.stdin.readlines()))) 
fd.close() 

내가 echo "foo" | mypythonscript.py을 실행하면 내가 대상 파일 /tmp/testrsyslogomoutput.txt에 "foo는"을 얻을 수 있습니다. 그러나 내가 rsyslog 내에서 실행할 때, 메시지가 rsyslog를 중지/재시작 할 때만 전송 된 것으로 보입니다. (어떤 점에서는 일부 버퍼가 플러시됩니다.)

처음에는 Rsyslog에 문제가 있다고 생각했습니다. 그래서 필자는 Python 프로그램을 rsyslog 구성을 변경하지 않고 쉘 1로 대체했습니다. 쉘 스크립트를 위해 rsyslog와 함께 완벽하게 작동하고 아래의 코드에서 볼 수 있듯이, 스크립트는 정말 간단하다 : 내 쉘 스크립트가 작동하지만 내 파이썬 하나하지 않기 때문에

#! /bin/sh 
cat /dev/stdin >> /tmp/testrsyslogomoutput.txt 

가, 내가 어딘가에서 실수를 믿는다 내 파이썬 코드하지만 어디에서 찾을 수 없습니다. 내 실수를 저에게 지적하면 좋을 것입니다. 이 파일을 읽는 완료 될 때까지

답변

0

나는 또한 이유를 의심 줄은 종료되지 않습니다 위해 rsyslog입니다. readlines()은 실제 EOF에 도달 할 때까지 돌아 오지 않아야합니다. 하지만 쉘 스크립트는 왜 다르게 작동합니까? 아마/dev/stdin을 사용하는 것이 그 이유 일 것입니다. 이 버전을 시도하고 여전히 매달려없이 실행하는 경우 참조 : 개방 대신 sys.stdin의, 파이썬에서는/dev/표준 입력을 읽어

#!/bin/sh 
cat >> /tmp/testrsyslogomoutput.txt 

을이 차이를 만드는 경우에는 수정을해야합니다.

편집 : 그래서 cat은 어떻게 든 stdin에서 기다리고 읽습니다.하지만 python은 차단하고 stdin이 모두 소모 될 때까지 기다립니다. 이상한. 을 read() 다음에 split("\n")으로 바꿔보십시오. 그러나이 시점에서 도움이 될지 의심 스럽습니다.

따라서 진단을 잊어 버리고 해결 방법을 시도해보십시오. stdin이 비 차단 I/O를 수행하도록하십시오. 다음은 그렇게하기로되어

import fcntl, os 

# Add O_NONBLOCK to the stdin descriptor flags 
flags = fcntl.fcntl(0, fcntl.F_GETFL) 
fcntl.fcntl(0, fcntl.F_SETFL, fl | os.O_NONBLOCK) 

message = sys.stdin.read().split("\n") # Read what's waiting, in one go 
fd = open('/tmp/testrsyslogomoutput.txt', 'a') 
fd.write("Receiving log message : \n%s\n" % ('-'.join(message))) 
fd.close() 

당신은 아마 python -u와 함께 그것을 사용하려고합니다. 희망 그것이 작동합니다!

+0

나는 당신이 제안한 것을 시도해 보았지만 아무런 차이가 없다. 이 사소한 쉘 스크립트로도 여전히 완벽하게 작동합니다. 또한/dev/stdin 내 python 스크립트에서 (readlines()없이) 읽으려고했는데 여전히 중단됩니다. –

+0

오 잘. 다음 생각 : python의 I/O를 -u 플래그로 python을 호출하여 방정식 밖으로 버퍼링하십시오. – alexis

+0

Alexis에게 도움을 주셔서 감사합니다. 파이썬 -u로 시도해 보았지만 아무 것도 변경하지 않았습니다. –

2

readlines : 사전에

감사는 반환하지 않습니다. 파이프 공급 표준이 끝나지 않으므로 readlines도 끝나지 않습니다. rsyslog를 중지하면 파이프가 닫히고 끝납니다.

0

대신 readline()을 사용하면 \n으로 돌아 오지만이 경우 한 줄만 쓰고 종료됩니다.

당신만큼 그들은 거기에 서면 라인을 유지하려면, 당신이 사용할 수있는 for 간단한 :

for line in fd: 
    fd.write("Receiving log message : \n%s\n" % (line) 
fd.close() 
+0

나는 이것을 시도했다. 문제는 동일하게 유지됩니다. 나는 sys.stdin과/dev/stdin을 반복하려고했는데 \ n이 보내질 때만 입력이 기록된다.위에 제안 된 것처럼 readline 대신 사용할 수도 없었습니다. –