¿Cómo saber cuándo ha terminado el subproceso después de usar os.kill ()?

Tengo un programa Python (precisamente, una aplicación Django) que inicia un subproceso usandosubprocess.Popen. Debido a las restricciones de arquitectura de mi aplicación, no puedo usarPopen.terminate() para terminar el subproceso yPopen.poll() para comprobar cuando el proceso ha terminado. Esto se debe a que no puedo mantener una referencia al subproceso iniciado en una variable.

En su lugar, tengo que escribir el ID de procesopid a un archivopidfile cuando se inicia el subproceso. Cuando quiero detener el subproceso, abro estepidfile y useos.kill(pid, signal.SIGTERM) para detenerlo

Mi pregunta es: ¿Cómo puedo saber cuándo ha finalizado realmente el subproceso? Utilizandosignal.SIGTERM Necesita aproximadamente 1-2 minutos para terminar finalmente después de llamaros.kill(). Primero pensé queos.waitpid() sería lo correcto para esta tarea, pero cuando lo llamo despuésos.kill() me daOSError: [Errno 10] No child processes.

Por cierto, estoy iniciando y deteniendo el subproceso desde una plantilla HTML utilizando dos formas y la lógica del programa está dentro de una vista Django. La excepción se muestra en mi navegador cuando mi aplicación está en modo de depuración. Probablemente también sea importante saber que el subproceso al que llamo en mi opinión (python manage.py crawlwebpages) llama a otro subproceso, a saber, una instancia de un rastreador de Scrapy. Escribo elpid de esta instancia de Scrapy a lapidfile Y esto es lo que quiero terminar.

Aquí está el código relevante:

def process_main_page_forms(request):
    if request.method == 'POST':
        if request.POST['form-type'] == u'webpage-crawler-form':
            template_context = _crawl_webpage(request)

        elif request.POST['form-type'] == u'stop-crawler-form':
            template_context = _stop_crawler(request)
    else:
        template_context = {
            'webpage_crawler_form': WebPageCrawlerForm(),
            'stop_crawler_form': StopCrawlerForm()}

    return render(request, 'main.html', template_context)

def _crawl_webpage(request):
    webpage_crawler_form = WebPageCrawlerForm(request.POST)

    if webpage_crawler_form.is_valid():
        url_to_crawl = webpage_crawler_form.cleaned_data['url_to_crawl']
        maximum_pages_to_crawl = webpage_crawler_form.cleaned_data['maximum_pages_to_crawl']

        program = 'python manage.py crawlwebpages' + ' -n ' + str(maximum_pages_to_crawl) + ' ' + url_to_crawl
        p = subprocess.Popen(program.split())

    template_context = {
        'webpage_crawler_form': webpage_crawler_form,
        'stop_crawler_form': StopCrawlerForm()}

    return template_context

def _stop_crawler(request):
    stop_crawler_form = StopCrawlerForm(request.POST)

    if stop_crawler_form.is_valid():
        with open('scrapy_crawler_process.pid', 'rb') as pidfile:
            process_id = int(pidfile.read().strip())
            print 'PROCESS ID:', process_id

        os.kill(process_id, signal.SIGTERM)
        os.waitpid(process_id, os.WNOHANG) # This gives me the OSError
        print 'Crawler process terminated!'

    template_context = {
        'webpage_crawler_form': WebPageCrawlerForm(),
        'stop_crawler_form': stop_crawler_form}

    return template_context

¿Que puedo hacer? ¡Muchas gracias!

EDITAR:

De acuerdo ala gran respuesta dada porJacek Konieczny, Podría resolver mi problema cambiando mi código en la función_stop_crawler(request) a lo siguiente:

def _stop_crawler(request):
    stop_crawler_form = StopCrawlerForm(request.POST)

    if stop_crawler_form.is_valid():
        with open('scrapy_crawler_process.pid', 'rb') as pidfile:
            process_id = int(pidfile.read().strip())

        # These are the essential lines
        os.kill(process_id, signal.SIGTERM)
        while True:
            try:
                time.sleep(10)
                os.kill(process_id, 0)
            except OSError:
                break
        print 'Crawler process terminated!'

    template_context = {
        'webpage_crawler_form': WebPageCrawlerForm(),
        'stop_crawler_form': stop_crawler_form}

    return template_context

Respuestas a la pregunta(2)

Su respuesta a la pregunta