After some more investigation I managed to create a suspended process and resume it later. Creating a suspended process using Popen and Windows is thankfully pretty simple.
First you will need to install pywin32 by running:
pip install pywin32
Once pywin32 is installed you can create a suspended process with subprocess.Popen
by using:
from win32process import CREATE_SUSPENDED
from subprocess import Popen
pipe = subprocess.Popen(<command>, <**kwargs>, creationflags=CREATE_SUSPENDED)
Resuming this suspended process, however, is quite a bit more difficult since it requires a PyHandle for the suspended thread. Unfortunately Popen doesn't return a Thread ID which is required to open a PyHandle for the suspended thread. As a work-around I ended up monkeypatching Popen's _execute_child function to store the Thread ID returned by _winapi.CreateProcess. Now that we have the suspended process' Thread ID we can resume the thread.
To resume a suspended process assuming you monkeypatched Popen to store the Thread ID use:
from win32api import OpenThread, CloseHandle
from win32con import THREAD_SUSPEND_RESUME
from win32process import ResumeThread
thread_handle = OpenThread(THREAD_SUSPEND_RESUME, <inherit handle (T/F)>, pipe.tid)
ResumeThread(thread_handle)
CloseHandle(thread_handle)
If anyone knows a way to get the Thread ID from Popen without monkeypatching _execute_child or any better methods of suspending and resuming a process please share!
Resources:
I also created a wrapper for subprocess.Popen that kills the child process when the parent dies if anyone would like to see my specific implementation.