Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Node.js에서 child_process spawn() 메서드로 Python 스크립트 실행하기

Node.js와 Python은 개발자와 웹 디자이너 사이에서 가장 선호되는 두 가지 주요 언어입니다. 하지만 Node.js가 Python에 비해 부족한 분야가 있는데, 바로 수치 계산과 과학적 연산(AI, 머신러닝, 딥러닝 등)입니다. 반면 Python은 NumPy, SciPy, TensorFlow 등 방대한 라이브러리 덕분에 과학 컴퓨팅 작업을 훨씬 쉽게 처리할 수 있습니다.

다행히 Node.js 애플리케이션 안에서도 Python을 백그라운드로 실행하고 그 결과를 반환받는 방식으로 Python 라이브러리를 그대로 활용할 수 있습니다.

이 글에서는 Node.js의 child_process 표준 라이브러리를 사용해 백그라운드에서 Python 프로세스를 생성(spawn)하고, 연산을 수행한 뒤 그 결과를 Node 프로그램으로 되돌려 받는 방법을 알아보겠습니다.

1. Python 스크립트 작성하기

먼저 진행 과정에서 메시지를 표준 출력(stdout)으로 출력하는 간단한 Python 스크립트를 작성해 보겠습니다. 이 스크립트는 명령줄 인자를 받아 처리하고, 시작과 종료 시각을 함께 출력합니다.

# 라이브러리 임포트
import sys, getopt, time
def main(argv):
    argument = ''
    usage = 'usage: myscript.py -f <sometext>'
    # 전달된 인자 파싱
    try:
        opts, args = getopt.getopt(argv,"hf:",["foo="])
    except getopt.GetoptError:
        print(usage)
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print(usage)
            sys.exit()
        elif opt in ("-f", "--foo"):
            argument = arg
    # 결과 출력
    print("Start : %s" % time.ctime())
    time.sleep( 2 )
    print('Foo is')
    time.sleep( 2 )
    print(argument)
    print("End : %s" % time.ctime())
if __name__ == "__main__":
main(sys.argv[1:])

실행 결과

>python myscript.py -f "Hello, Python"
Start : Wed Feb 20 07:52:45 2019
Foo is
Hello, Python
End : Wed Feb 20 07:52:49 2019

-f 대신 --foo 옵션을 사용해도 위와 동일한 출력이 생성됩니다. 또한 -h 옵션을 붙여 실행하면 사용법 안내 메시지가 출력됩니다.

>python myscript.py --foo "Hello, Python"
>python myscript.py –h

출력

usage: myscript.py -f <Hello, Python>

2. Node.js와의 상호작용

Node.js 스크립트는 먼저 Python 스크립트를 호출한 다음, 스크립트의 출력을 클라이언트에 전달하고 화면에 렌더링하는 방식으로 Python과 상호작용합니다.

그럼 Node.js 스크립트를 만들어 spawn() 메서드로 자식 프로세스(child process)를 생성해 보겠습니다.

server.js

const path = require('path')
const {spawn} = require('child_process')
/**
    * python myscript 실행, `-u` 옵션으로 콘솔 출력 버퍼링 방지
    * @return {ChildProcess}
*/
function runScript(){
    return spawn('python', [
        "-u",
        path.join(__dirname, 'myscript.py'),
        "--foo", "some value for foo",
    ]);
}
const subprocess = runScript()
// 스크립트 출력 출력
subprocess.stdout.on('data', (data) => {
   console.log(`data:${data}`);
});
subprocess.stderr.on('data', (data) => {
   console.log(`error:${data}`);
});
subprocess.stderr.on('close', () => {
   console.log("Closed");
});

위 스크립트는 .on('data', callback)을 통해 자식 프로세스의 출력을 실시간으로 전달받습니다. 여기서 한 가지 중요한 점은, Python이 출력을 버퍼링하지 않도록 -u 플래그를 반드시 지정해야 한다는 것입니다. 이 옵션이 없으면 프로그램 실행이 완전히 끝날 때까지 print() 문의 출력이 data 이벤트로 전달되지 않습니다.

실행 결과

>node server.js
data:Start : Wed Feb 20 10:56:11 2019
data:Foo is
data:some value for foo
data:End : Wed Feb 20 10:56:15 2019
Closed

이처럼 spawn() 메서드를 활용하면 Node.js 애플리케이션에서 Python의 강력한 과학 컴퓨팅·머신러닝 라이브러리를 손쉽게 결합해 사용할 수 있습니다. stdout과 stderr 이벤트를 적절히 처리하면 Python 스크립트의 정상 출력과 에러 메시지를 모두 실시간으로 모니터링할 수 있습니다.