PHP에서 exec()로 Python 코드 실행하고 결과 받아내기


업무 중에 웹상에서 서버에 업로드 되어 있는 파이썬(Python) 스크립트를 실행하고 결과를 받아내서 다시 페이지에 뿌려주는 작업을 한 적이 있다. 두 스크립트 언어 모두 내가 사랑해 마지 않는 언어이고, 각각 사용한 기간도 짧지 않긴 하다만 두 언어를 연동해서 뭔가를 만든 적은 이번이 처음이었다. (예전에 파이썬과 C++을 붙인 적은 있긴 하다만…)

아무튼, 기본적인 작업 흐름은 간단했다. 먼저 작업의 중심이 되는 파이썬 코드는 command 입력으로 필요한 파라미터들을 받을 수 있도록 수정을 좀 했고, PHP가 리턴값을 읽을 수 있도록 print()도 수정을 해두었다. 그 다음, 이 파이썬 코드를 command로 호출할 PHP 코드를 작성했는데 핵심은 아래와 같다.

$pyout = exec('python heavy_script.py 100 50');
echo $pyout;

웹페이지에서는 Ajax로 간단하게 text 결과를 받아서 처리를 한 다음 보여주는 걸로 구성을 했고, 시험 삼아 간단한 테스트 코드를 작성해서 해보니 큰 문제는 없었다. 그러나, 코딩을 이제 뜨문 뜨문 해서인지 실제 프로젝트에서는 문제가 생겼는데 바로 파이썬 코드 실행이 너무 오래 걸려서 PHP가 리턴값을 제대로 받지 못하는 것이다. 물론 php.ini 파일을 수정해서 timeout 시간도 조정해보고 Ajax 코드에서도 동일하게 했지만, 근본적으로 파이썬 코드가 완전히 끝날 때까지 기다리지 않는 문제가 있었다.

이리저리 폭풍 검색해본 결과, 아래와 같은 간단한(?) 해결책을 찾아서 적용했고 문제 없이 무거운 파이썬 코드 실행을 끝까지 기다렸다가 PHP에서 정상적으로 리턴을 하게 되었다.

$pyout = exec('python heavy_script.py 100 50 2>&1');
echo $pyout;

위 코드에서 달라진 점은 command 끝에 2>&1 이 부분이 추가된 것인데, 해석을 해보자면 표준 에러(2)를 보내는데(>) 어디로 보내냐면 표준 출력(1)으로 함께(&) 보내라는 뜻이다. 처음에 봤을땐 무슨 암호문인가? 했지만 저 표기법은 파일디스크립터와 관련된 내용이라고 한다. 솔직히 여태까지 몰랐던 내용이라 지금 이렇게 귀차니즘을 무릅쓰고 블로그에 기록해 두는 거긴 한데… 혹시 나처럼 같은 상황에서 헤매고 계실 분이 계실까봐 훨씬 잘 설명된 글을 아래 링크로 공유한다.

https://blogger.pe.kr/369

프로그래밍의 세계는 참 놀랍다. 배워도 끝이 없고 알면 알수록 더 모르는게 많아지니…


답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다