증상: 스스로 새 판을 받고 os.execv 로 다시 뜨게 만든 파이썬 프로그램이 재시작 뒤 흔적 없이 사라집니다.
원인: 윈도우 파이썬의 os.execv 는 인자를 이을 때 따옴표를 붙이지 않아, 띄어쓰기가 든 경로가 잘린 채 넘어갑니다.
해결: subprocess.Popen 에 인자를 목록으로 넘겨 새 프로세스를 띄우고 os._exit(0) 으로 끝냅니다.
리눅스에서 잘 쓰던 자기 재시작 코드를 윈도우에 그대로 가져가면 조용히 실패할 수 있습니다. 특히 프로그램 폴더 이름에 띄어쓰기가 있을 때입니다. 실제로 백그라운드로 도는 파이썬 작업 하나가 이 때문에 멈췄습니다.
업데이트 뒤 프로그램이 사라졌다
이 프로그램은 서버에서 새 판을 받으면 파일을 바꾸고 os.execv 로 자기 자신을 다시 띄우게 되어 있었습니다. 그런데 어느 업데이트 뒤로 프로그램이 다시 뜨지 않았습니다.
pythonw 로 창 없이 돌던 프로그램이라 오류 창도, 로그도 남지 않았습니다. 겉으로 보인 증거는 서버 쪽에서 3분마다 오던 접속이 끊겼다는 것 하나뿐이었습니다.
execv 가 경로를 따옴표로 감싸지 않는다
윈도우에는 리눅스의 exec 같은 "현재 프로세스를 바꿔 끼우는" 동작이 따로 없어서, 파이썬은 인자 목록을 한 줄의 명령줄로 이어 새 프로세스를 만듭니다. 이때 윈도우 파이썬의 os.execv 는 각 인자를 따옴표로 감싸지 않습니다.
그래서 C:\My Tools\worker\run.py 같은 경로는 새 프로세스에서 C:\My 와 Tools\worker\run.py 두 인자로 갈라집니다. 파이썬은 C:\My 라는 스크립트를 찾지 못하고 바로 끝납니다. 창이 없으니 그 오류를 볼 사람도 없습니다.
| 방식 | 띄어쓰기 경로 | 비고 |
|---|---|---|
| os.execv(sys.executable, [...]) | 잘린 경로로 넘어가 죽음 | 윈도우에서 따옴표를 붙이지 않음 |
| subprocess.Popen([...]) 목록 | 정상 | list2cmdline 이 따옴표로 감싸 줌 |
| subprocess.Popen("문자열") | 직접 따옴표를 넣어야 함 | 실수하기 쉬움 |
Popen 목록으로 새로 띄우고 스스로 끝내기
import os, sys, subprocess
DETACHED_PROCESS = 0x00000008
CREATE_NEW_PROCESS_GROUP = 0x00000200
def restart_self():
script = os.path.abspath(sys.argv[0])
subprocess.Popen(
[sys.executable, script] + sys.argv[1:],
creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP,
close_fds=True,
)
os._exit(0)
인자를 목록으로 넘기면 파이썬이 subprocess.list2cmdline 으로 띄어쓰기가 든 인자를 알아서 따옴표로 감쌉니다. 새 프로세스를 부모와 떼어 띄운 뒤, 지금 프로세스는 os._exit(0) 으로 바로 끝냅니다.
고칠 때 판 번호를 올리지 않는다
여기서 함정이 하나 더 있었습니다. 재시작 방식을 고친 새 판을 배포하면서 판 번호를 올리면, 디스크에 남은 옛 판이 그 새 판을 받아 옛 방식(execv)으로 재시작하다가 또 죽습니다.
그래서 재시작 방식만 고칠 때는 판 번호를 올리지 않고 파일을 바꿔 두었습니다. 옛 판이 업데이트를 받으러 가지 않게 하는 것이 핵심입니다.
고쳐졌는지 확인하는 법
멀리 있는 PC 에서 도는 프로그램이라면 로그 문구가 아니라 접속 간격으로 살아 있는지 봅니다. 3분마다 오던 접속이 재시작 뒤에도 같은 간격으로 이어지면 새 프로세스가 제대로 뜬 것입니다.
가까이 있는 PC 라면 띄어쓰기가 든 폴더에 스크립트를 두고 재시작 함수를 한 번 불러 본 뒤, 새 프로세스가 떠 있는지 프로세스 목록으로 확인하면 됩니다.
Get-CimInstance Win32_Process -Filter "Name like 'python%'" | Select-Object ProcessId, CommandLine
이 재현 절차는 따로 돌려 보지 못했습니다. 그래서 여기까지는 확인하지 못했고, 멀리 있는 PC 는 접속 간격을 기준으로 보기로 정했습니다.
왜 이렇게 늦게 알았나
이 문제는 평소에는 드러나지 않습니다. 재시작은 새 판이 나왔을 때만 일어나고, 개발하는 PC 의 폴더 이름에는 띄어쓰기가 없을 수도 있기 때문입니다. 띄어쓰기가 있는 폴더에 설치된 PC 에서 업데이트가 일어난 순간에만 죽습니다.
게다가 창 없이 도는 프로그램이라 죽는 장면을 볼 수 없었습니다. 멀리 있는 PC 의 프로그램이 스스로를 고치는 구조라면, 오류를 서버로 알리는 길과 접속 간격 같은 생존 신호를 처음부터 함께 만들어 두는 것이 좋습니다. 이번에도 결국 접속 간격이 유일한 단서였습니다.
확인한 환경
| 항목 | 내용 |
|---|---|
| 운영체제 | 윈도우 노트북 |
| 실행 방식 | pythonw 로 도는 자기 갱신 프로그램 |
| 경로 조건 | 프로그램 폴더 이름에 띄어쓰기 포함 |
관련 글: pythonw 인데도 CMD 창이 뜰 때, 파이썬에서 실패가 조용히 삼켜지는 세 가지
이 글의 내용은 2026년 10월 5일에 마지막으로 확인했습니다. 틀린 곳을 발견하시면 연락처로 알려 주세요.