즉시 Python stdout을 파일에 쓰기

즉시 Python stdout을 파일에 쓰기

Python 스크립트에서 텍스트 파일( )로 stdout을 쓰려고 하면 python script.py > log명령이 시작될 때 텍스트 파일이 생성되지만 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의 버퍼링을 인식하지 못했습니다.

답변1

이는 일반적으로 프로세스의 STDOUT이 터미널이 아닌 다른 곳으로 리디렉션될 때 출력이 일부 운영 체제별 크기(많은 경우 4k 또는 8k)의 버퍼에 버퍼링되기 때문에 발생합니다. 대조적으로, 터미널로 출력할 때 STDOUT은 라인 버퍼링되거나 전혀 버퍼링되지 않으므로 각 문자 \n또는 모든 문자 다음에 출력이 표시됩니다.

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

stdbuf -oL python script.py > log

이제 이렇게 하면 tail -F log빌드되는 즉시 각 출력 줄을 볼 수 있습니다.


또는 각 인쇄 후에 출력 스트림을 명시적으로 플러시하면 동일한 효과를 얻을 수 있습니다. 처럼 보인다sys.stdout.flush()이는 Python으로 구현해야 합니다. Python 3.3 이상을 사용하는 경우 이 함수에는 이 작업을 수행하는 키워드 print도 있습니다 : .flushprint('hello', flush=True)

답변2

이 작업을 수행해야 합니다.

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

stdoutPython 버퍼는 기본적으로 버퍼이므로 sys.stdout.flush()여기서는 플러시 버퍼를 사용합니다.

-u또 다른 해결책은 (버퍼되지 않은) 스위치를 사용하는 것입니다 python. 따라서 다음도 작동합니다.

python -u script.py >> log

답변3

Python 자체의 버퍼링되지 않은 출력 옵션을 사용한 테마 변형이 #!/usr/bin/python -u첫 번째 줄로 사용됩니다.

이 추가 인수는 효과가 없으므로 다음 두 단계로 실행하거나 수행하도록 #!/usr/bin/env python선택할 수 있습니다 .PYTHONUNBUFFERED=1 ./my_scriipt.py > output.txt

$ export PYTHONUNBUFFERED=1
$ ./myscript.py

답변4

flush=True당신은 에 전달해야print기능:

import time

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

문서에 따르면 기본적으로 print새로 고침에 관한 어떤 것도 강제로 수행되지 않습니다.

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

sysstrems에 대한 문서는 다음과 같이 말합니다.

대화형인 경우 표준 스트림은 라인 버퍼링됩니다. 그렇지 않으면 일반 텍스트 파일처럼 블록 버퍼링됩니다. -u명령줄 옵션을 사용하여 이 값을 재정의 할 수 있습니다 .


이전 버전의 Python을 사용하고 있다면 다음을 호출해야 합니다.flush행동 양식sys.stdout개울:

import sys
import time

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

관련 정보