왜`BrokenPipeError`가 파이프 된 스트림의 크기에 의존합니까?
On 2월 15, 2021 by admin 다음 스크립트는 head
<과 같은 명령으로 파이프 될 때 BrokenPipeError: [Errno 32] Broken pipe
를 발생시킵니다. / div> (앞으로 줄 줄 수가 Python 스크립트로 인쇄 된 줄 수를 초과하지 않는 경우)
for i in range(16386): print("")
$ python test-pipe.py | head -1 Traceback (most recent call last): File "test-pipe.py", line 2, in <module> print("") BrokenPipeError: [Errno 32] Broken pipe
내 이해 (이 답변 및 이 질문에 대한 답변 )은 Python 프로세스가 완료되기 전에 파이프가 닫히면 오류가 발생한다는 것입니다.
그러나 반복 범위를 1에서 16385로 줄이면 오류가 발생하지 않습니다 (이 임계 값이 모든 시스템에서 동일한 지 확실하지 않으므로 높고 낮은 숫자를 시도하십시오. 재생산). 처음에는 이것이 파이프 버퍼 크기와 관련이 있다고 생각했지만 저에게는 64K입니다 (M=0; while printf A; do >&2 printf "\r$((++M)) B"; done | sleep 999
에 따르면 그 이유가 아닌 것 같습니다.
왜 발생이 BrokenPipeError
파이프되는 항목의 크기에 따라 달라 집니까?
이것은 Linux 5.4.15-arch1의 Python 3.8.1에서 발생합니다. -1.
댓글
Answer
왜 발생 BrokenPipeError가 파이프되는 항목의 크기에 따라 달라 지나요?
더 많은 것을 작성하는 데 더 많은 시간이 걸리고 파이썬이 작성을 완료하기 전에 파이프 라인의 오른쪽이 죽을 수 있기 때문입니다. 또한 파이썬이 파이프 버퍼에 맞는 것보다 더 많이 쓰려고하면 head -1
를 차단하고 종료 할 충분한 시간을 제공합니다.
head -1
는 살아서 죽는 데 약간의 시간이 걸립니다. 파이썬은 그 시간을 사용하여 파이프 버퍼에 맞는 경우 모든 내용을 작성하고 성공적으로 종료 할 수 있습니다. 커널이 어떤 순서로든 파이프 라인의 양쪽을 자유롭게 예약 할 수 있고 적절하다고 판단되는 한 head -1
시작을 지연시킬 수 있기 때문에 예측하기 어렵습니다. 언제든지 중지하십시오.
>>> python3 -c "for i in range(50000): print("")" | sleep .01 Traceback (most recent call last): File "<string>", line 1, in <module> BrokenPipeError: [Errno 32] Broken pipe >>> python3 -c "for i in range(50000): print("")" | sleep .1 # OK!
그러나 파이썬이 파이프에 맞는 것보다 더 많은 것을 쓰려고하면 또는 SIGPIPE
는 시간에 상관없이 결국 :
>>> python3 -c "for i in range(100000): print("")" | sleep 20 Traceback (most recent call last): File "<string>", line 1, in <module> BrokenPipeError: [Errno 32] Broken pipe
하지만 저에게는 64K입니다 … 그래서 그 이유가 아닌 것 같습니다.
출력이 터미널이 아닐 때 파이썬은 전체 버퍼링 을 사용하고 있다는 것을 명심하십시오. 한 줄씩 또는 한 바이트 씩 쓰지 않고 일부 크기의 청크로 기록합니다.
>>> strace -s3 -e trace=write python3 -c "for i in range(50000): print("")" | sleep .3 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 842) = 842 +++ exited with 0 +++
head -1
명령 대신:
명령을 사용하는 크기 종속성이 있습니다.python3 -c "for i in range(10000): print(i)" | : </dev/tcp/unix.stackexchange.com/https
. 범위, 깨진 파이프로 실패한 파이썬.