문제 세팅을 위해 로컬 스트레스를 돌리는 경우가 왕왕 있습니다. 이럴 때 파이썬 스크립트를 자주 사용하는 편입니다. 스트레스를 돌릴 때, diff 함수를 상당히 자주 사용합니다. 수만개의 스트레스를 자동으로 돌리는 방법이 없을까요? 이 글에서는 subprocess run 함수로 이러한 일을 하는 방법을 알아봅니다.
명령어 결과 얻어오기
test/diff 디렉토리에 1.in, 2.in, 3.in 이렇게 3개의 파일이 있습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2024/04/sub_run1.png)
1.in과 2.in에는 1이, 3.in에는 3이 있습니다. diff는 몇 개의 파일을 비교하는데요. 두 개의 파일을 비교할 때 리턴값은 아래와 같습니다.
- 두 파일이 같으면 0
- 두 파일이 다르면 1
- 에러가 발생하면 2
실행을 시켜 보겠습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2024/04/sub_run2.png)
diff 1.in 2.in 명령어를 실행시켰습니다. 그리고 echo $?를 실행시켰습니다. 여기서, $?는 이전에 실행한 명령어의 리턴값을 가져옵니다. diff는 두 파일이 같으면 0을 리턴합니다. 1.in과 2.in은 같은 내용이 있었기 때문에, 0을 돌려줍니다.
![](https://codingdog.pe.kr/wp-content/uploads/2024/04/sub_run3.png)
반대로, 1.in과 3.in을 비교해 봅시다. 1.in에는 1이 있지만 3.in에는 3이 있습니다. 둘이 다릅니다. 따라서, 1이 리턴되게 됩니다. 두 솔루션을 비교할 때, 결과 파일 2개를 diff의 리턴값으로 비교하면 된다는 것을 알 수 있습니다. local stress 어렵지 않게 구축 가능합니다.
파이썬 subprocess run 함수의 returncode 알아보기
이제, 문제의 함수를 보도록 합시다.
![](https://codingdog.pe.kr/wp-content/uploads/2024/04/sub_run9.png)
엄청나게 많은 인자들이 있습니다. 이 글에서 언급하는 keyword는 2개입니다.
- args
- stdout
args는 명령어를 의미합니다. 예를 들어, ls -l의 경우 [“ls”, “-l”]을 넘겨주면 됩니다. 맨 밑에 보시면, 인자로 넘겨준 args를 가지고 command를 돌립니다. 그리고, CompletedProcess 인스턴스를 돌려준다고 되어 있어요.
![](https://codingdog.pe.kr/wp-content/uploads/2024/04/sub_run4.png)
이 CompletedProcess 인스턴스에는 returncode가 있습니다. 명령어를 실행한 후의 exitcode 입니다. 이것이 핵심입니다. diff로 두 파일을 비교하는 명령어를 실행시켰다면 어떤 값이 저장될까요?
- 두 파일이 같다면 0
- 두 파일이 다르다면 1
- 에러가 발생하면 2
이제, 예제를 보도록 하겠습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2024/04/sub_run10.png)
먼저 1번 예제입니다. run의 args로 [“diff”, “1.in”, “2.in”]을 넘겨주었습니다. 이는 “diff 1.in 2.in” 명령어를 실행한다는 의미입니다. 이 명령어의 exitCode를 받는데, 같기 때문에 0을 받습니다. 다음, 2번째 run은 “diff 1.in 3.in”을 실행합니다. 1.in과 3.in은 다르기 때문에 1이 리턴됩니다. 결과를 볼까요?
![](https://codingdog.pe.kr/wp-content/uploads/2024/04/sub_run6.png)
0과 1이 나옵니다. 그런데, 중간에 출력이 들어갑니다. 이는, diff 명령어가 두 파일이 다르면 stdout에 출력해 버리기 때문입니다.
여기서 핵심은 파이썬 subprocess run 함수가 CompletedProcess 인스턴스를 리턴합니다. 이 리턴값의 returncode를 가져오면 명령어의 리턴값을 얻어올 수 있게 됩니다.
diff 출력 제외하기
run 함수를 실행시킬 때, diff 함수의 출력을 제외하려면 어떻게 해야 할까요? 간단합니다. stdout을 표준 출력으로 하는 것이 아니라, 다른 파일로 해 버리면 됩니다. subprocess.DEVNULL은 아무 파일에도 출력하지 않고 버립니다.
![](https://codingdog.pe.kr/wp-content/uploads/2024/04/sub_run7.png)
예제 2번 프로그램을 보겠습니다. 2번째 run 함수의 stdout에 subprocess.DEVNULL을 넘겨주었습니다. 이는, 명령어를 실행시키는 프로세스의 표준 출력을 DEVNULL로 덮어쓴다는 의미입니다.
![](https://codingdog.pe.kr/wp-content/uploads/2024/04/sub_run8.png)
실행 결과는 위와 같습니다. 예제 1과는 다르게 다른 부분이 출력되지 않았습니다. 이는, 자식 프로세스인 diff의 output이 /dev/null로 출력했기 때문입니다. output 캡쳐하는 부분은 다음 글에 자세히 알아보도록 하겠습니다.