Python으로 멀티프로세스 코드를 작성하다보면 한번씩 BrokenPipeError를 만나게 된다. 이게 무슨 의미인지 이해하는 과정에서 찾아본 자료들을 정리하고자 한다.
BrokenPipeError의 정의
BrokenPipeError는 Pipe가 부러져서 생긴 오류라는 의미다. 그럼 Pipe가 무엇인지에 대해서 먼저 이해해야한다.
파이프 (Pipe)
Pipe는 운영체제에서 서로다른 프로세스의 입출력을 연결하는 방법을 의미한다. 예컨데, A 프로세스에서 생긴 출력을 B 프로세스의 입력으로 연결하는 수단을 Pipe라고 생각하면 이해하기 쉽다.
파이프 연결 예시
예를 들어, 아래와 같은 두 프로세스가 있다고 생각해보자.
echo "hello"
이 프로세스는 표준출력(stdout)에 "hello"라는 문자열을 쓴다(write).
python -c "print(f'my stdandard input is {input()}')"
이 프로세스는 표준입력(stdin)을 읽어서(read) 표준출력(stdout)으로 쓴다(write).
이 때, 전자의 표준출력(stdout)을 후자의 표준입력(stdin)으로 "|"를 활용해 연결할 수 있고 이를 Pipe라고 부른다.
$ echo "hello" | python -c "print(f'my standard input is {input()}')"
my standard input is hello
파이프 부러짐 (Broken Pipe)
파이프가 부러졌다는 것은 후자의 프로세스가 먼저 종료되어서 전자 프로세스에서 전달되는 표준출력을 파이프를 통해 후자 프로세스의 표준입력에 전달하려고 시도했을 때, 후자 프로세스가 받아들이지 못하는 상황을 의미한다. 즉, 전자 프로세스의 표준출력과 후자 프로세스의 표준입력을 연결하는 파이프의 연결이 끊겼다, 부러졌다라고 얘기할 수 있다.
논의점. 전자의 프로세스가 먼저 종료되어 후자 프로세스가 표준입력으로부터 읽기를 시도했을 때에도 파이프 부러짐(Broken Pipe)라고 얘기할 수 있을까?
파이프 부러짐을 알리는 신호들: SIGPIPE와 BrokenPipeError
우리가 사용하는 운영체제에서는 Broken Pipe가 발생했을 때, 전자 프로세스에게 Pipe가 부러졌다는 신호를 SIGPIPE라는 시그널로 알린다. Python은 이를 BrokenPipeError로 변환시켜 에러를 발생시킨다.
BrokenPipeError 시뮬레이션
BrokenPipeError를 시뮬레이션 하기 위해 다음과 같은 상황을 생각해볼 수 있다.
$ python -c "print('\n'.join(map(str, range(30000))))" | head -n 5
0
1
2
3
4
Traceback (most recent call last):
File "<string>", line 1, in <module>
BrokenPipeError: [Errno 32] Broken pipe
전자 프로세스는 0부터 3만까지의 숫자를 3만줄에 걸쳐 표준출력에 쓴다. 후자 프로세스는 표준입력으로부터 5줄을 읽어 표준출력에 쓴다. 후자 프로세스는 전자 프로세스로부터 파이프를 통해 전달되는 표준입력 5줄을 읽어 표준출력에 쓴 다음, 종료된다. 하지만, 전자 프로세스의 경우, 5줄 외에 나머지 29995줄의 데이터를 후자 프로세스와 연결된 파이프에다가 계속 쓰게된다. 이같은 상황을 운영체제가 탐지하였을 때, 전자 프로세스에 SIGPIPE 시그널을 보낸다. 그리고, Python은 이를 BrokenPipeError로 에러를 발생시켜 전자 프로세스가 멈추게 된다.
물론 파이프 부러짐 현상이 탐지되지 않는 경우도 존재한다. 예를 들어, 3만이 아닌 300 정도의 작은 숫자로 변경하면 BrokenPipeError가 발생하지 않는다. 이는, 파이프가 부러졌음을 운영체제가 탐지하는 시점이 전자 프로세스가 300줄을 표준출력에 쓰는 것보다 늦었기 때문이라고 예측해볼 수 있다.
References
https://www.geeksforgeeks.org/broken-pipe-error-in-python/
https://docs.python.org/3/library/signal.html#note-on-sigpipe
'Engineering' 카테고리의 다른 글
View를 리턴하는 것과 Copy를 리턴하는 것 (0) | 2024.12.24 |
---|---|
json과 ujson의 차이점 (0) | 2024.09.12 |
배열 내에 k번째로 작은 수 구하기 (0) | 2024.05.09 |
Instruction tuned model과 eos 토큰 (1) | 2024.02.27 |
Github Private Repo로 Fork하기 (0) | 2024.01.17 |