본문 바로가기

Language/Python

[Python] 외부 파일 실행 시에 cmd 쉘을 발생시키지 않는 ShellExecute

파이썬에서 외부 파일을 실행하기 위해서 많이들 사용하는 명령어는 다음의 것들일 것이다.


 - os.system("실행할 파일")

 - os.popen("실행할 파일")

 - subprocess.call("실행할 파일")


이 3가지 중 os 모듈을 이용하는 것은 실행한 파일이 종료되기 전까지는 계속 메모리에 상주가 된다.

os.system과 os.popen은 cmd에서 명령어를 입력하는 것과 같은 동작을 해준다.

즉, "실행할 파일"을 구동시키게 되면 실행된 것들의 프로세싱이 끝나기 전 까지는 프로세스로서 cmd.exe가

메모리에 상주되는 것이다.


subprocess만이 cmd를 통하지 않고 바로 실행을 시켜주지만 여전히 "실행할 파일"은 본인을 실행시킨 프로세스에

자식 프로세스로 귀속이 된다.

(cmd를 거치지는 않았지만 python.exe에 귀속되어진다.)






[그림. 1] 3가지 메소드의 프로그램 실행




[그림. 1]은 위의 3가지 메소드를 이용하여 "계산기", "메모장", "그림판"을 실행한 결과이다.

(os 모듈은 cmd를 모두 이용하므로 스레드를 할당해서 실행해야 두 개가 동시 실행된다.)


import os, subprocess, thread

calc = ("c:\windows\system32\\calc.exe")
notepad = ("c:\windows\system32\\notepad.exe")
paint = ("c:\windows\system32\\mspaint.exe")

def os_system(path):
os.system(path)


def os_popen(path):
os.popen(path)


thread.start_new_thread(os_system, (calc,))
thread.start_new_thread(os_popen, (notepad,))


subprocess.call(paint)


subprocess.call만이 바로 그림판을 실행해주고 나머지들은 전부 cmd를 열고 그 쉘을 통해 명령을 수행시켜준다.


만약 내가 어떤 외부 파일을 실행하고자 한다면??

그게 잠깐 구동되고 종료되는 거라면야 뭐 cmd도 같이 종료가 되니 크게 문제될 것은 없겠지만...


위와 같이 아예 창을 띄우는 프로그램을 구동시켜야 하는 경우에는 얘기가 달라진다.

창이 띄워져 있는 동안은 cmd도 같이 부모 프로세스로 메모리를 잡아 먹기 때문이다.

(subprocess 역시도 cmd는 안 띄우지만 python.exe가 부모 프로세스로서 메모리를 잡아먹게 된다.)


이럴 때는 Windows API인 ShellExecuteA 나 ShellExecuteEx 메소드들을 이용해주면 나을 듯 하다.

Windows API이기 때문에 파이썬에서는 ctypes 모듈을 이용하여 사용할 수 있다.


예제에서는 ShellExecuteA 만을 사용해보도록 한다.

(솔직히 ShellExecuteEx 함수는 아직 인자값이 뭘 뜻하는지 제대로 잘 안 알아봤다. -_-)


이 놈은 스레드를 별도로 구현해줄 필요도 없다. 그냥 바로 한 방에 다 써주면 됨.


import ctypes

calc = ("c:\windows\system32\\calc.exe")
notepad = ("c:\windows\system32\\notepad.exe")
paint = ("c:\windows\system32\\mspaint.exe")

ctypes.windll.shell32.ShellExecuteA(0, 'open', calc, None, None, 1)
ctypes.windll.shell32.ShellExecuteA(0, 'open', notepad, None, None, 1)
ctypes.windll.shell32.ShellExecuteA(0, 'open', paint, None, None, 1)



해당 메소드의 MSDN 문서 링크는 다음과 같으며 사용되는 인자 값은 각자 체크하도록... -_-


https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx






[그림. 2] 도스 쉘을 통하지 않고 바로 실행


3개의 프로그램 모두 독립적으로 실행이 되었다.

실제 Process Monitoring 툴을 이용하여 확인을 해봐도 cmd.exe의 반응은 전혀 일어나지 않고, 부모 프로세스 없이

독립적으로 실행이 되기 때문에 외부의 어떤 파일을 구동하기 위한 작업에는 가장 적합하지 않을까 싶다.