Python stdout을 즉시 파일로 작성 초마다 stdout으로

Python 스크립트에서 텍스트 파일 ( python script.py > log) 로 stdout을 쓰려고하면 명령이 시작될 때 텍스트 파일이 작성되지만 실제 내용은 Python 스크립트가 완료 될 때까지 작성되지 않습니다. 예를 들면 다음과 같습니다.

script.py :

import time
for i in range(10):
    print('bla')
    time.sleep(5)

로 호출하면 5 초마다 stdout으로 인쇄 python script.py되지만 호출 python script.py > log하면 스크립트가 완료 될 때까지 로그 파일의 크기가 0으로 유지됩니다. 스크립트의 진행 상황을 따를 수 있도록 로그 파일에 직접 쓸 수 tail있습니까 (예 🙂 ?

편집 그것은 python -u script.py트릭 을 수행하는 것으로 나타났습니다 . 나는 stdout의 버퍼링에 대해 몰랐습니다.



답변

이는 일반적으로 프로세스 STDOUT이 터미널 이외의 다른 경로로 경로 재 지정 될 때 출력이 일부 OS 특정 크기 버퍼 (대부분의 경우 4k 또는 8k)로 버퍼링되기 때문에 발생합니다. 반대로, 터미널로 출력 할 때 STDOUT은 라인 버퍼링되거나 전혀 버퍼링되지 않으므로 \n각 문자 다음 또는 각 문자에 대한 출력을 볼 수 있습니다 .

일반적으로 stdbuf유틸리티를 사용하여 STDOUT 버퍼링을 변경할 수 있습니다 .

stdbuf -oL python script.py > log

이제이면 tail -F log생성되는 즉시 각 라인 출력을 볼 수 있습니다.


또는 각 인쇄 후 출력 스트림의 명시 적 플러싱이 동일해야합니다. sys.stdout.flush()파이썬에서 이것을 달성 해야하는 것처럼 보입니다 . Python 3.3 이상을 사용하는 경우 print함수에는 다음과 같은 flush키워드 도 있습니다 print('hello', flush=True).


답변

이것은 일을해야합니다 :

import time, sys
for i in range(10):
    print('bla')
    sys.stdout.flush()
    time.sleep(5)

파이썬이 stdout기본적으로 sys.stdout.flush()버퍼링하므로 버퍼를 플러시하는 데 사용 했습니다.

또 다른 해결책은의 -u(언 버퍼링 된) 스위치 를 사용하는 것 입니다 python. 따라서 다음도 수행됩니다.

python -u script.py >> log

답변

버퍼되지 않은 출력에 파이썬 자체 옵션을 사용하는 주제에 대한 변형 #!/usr/bin/python -u은 첫 번째 줄로 사용하는 것 입니다.

#!/usr/bin/env python그 여분의 인수거야하지 작업, 그래서 대안으로, 하나는 실행할 수 PYTHONUNBUFFERED=1 ./my_scriipt.py > output.txt또는 두 단계를 수행합니다

$ export PYTHONUNBUFFERED=1
$ ./myscript.py

답변

당신은 통과해야 flush=True받는 print기능 :

import time

for i in range(10):
    print('bla', flush=True)
    time.sleep(5)

설명서에 따르면 기본적으로 print플러싱에 대해서는 아무것도 적용하지 않습니다.

출력이 버퍼링되는지 여부는 일반적으로 파일에 의해 결정되지만
flush키워드 인수가 true이면 스트림이 강제로 플러시됩니다.

그리고 sysstrem에 대한 문서 는 다음과 같이 말합니다.

대화식 일 때 표준 스트림은 라인 버퍼링됩니다. 그렇지 않으면 일반 텍스트 파일처럼 차단됩니다. -u명령 행 옵션 으로이 값을 대체 할 수 있습니다 .


고대 버전의 파이썬에 갇혀 있다면 스트림 의 flush메소드 를 호출 해야 sys.stdout합니다.

import sys
import time

for i in range(10):
    print('bla')
    sys.stdout.flush()
    time.sleep(5)