Wie kann ich herausfinden, wann der Subprozess nach Verwendung von os.kill () beendet wurde?

Ich habe ein Python-Programm (genau genommen eine Django-Anwendung), mit dem ein Unterprozess gestartet wirdsubprocess.Popen. Aufgrund von Architekturbeschränkungen meiner Anwendung kann ich nicht verwendenPopen.terminate() zum Beenden des Unterprozesses undPopen.poll() um zu überprüfen, wann der Prozess beendet wurde. Dies liegt daran, dass ich keinen Verweis auf den gestarteten Unterprozess in einer Variablen halten kann.

Stattdessen muss ich die Prozess-ID schreibenpid in eine Dateipidfile wenn der Unterprozess startet. Wenn ich den Subprozess stoppen möchte, öffne ich diesenpidfile und verwendenos.kill(pid, signal.SIGTERM) um es zu stoppen.

Meine Frage ist: Wie kann ich herausfinden, wann der Teilprozess wirklich beendet wurde? Verwendensignal.SIGTERM Es dauert ungefähr 1-2 Minuten, um nach dem Anruf endgültig zu beendenos.kill(). Zuerst habe ich das gedachtos.waitpid() wäre das richtige für diese aufgabe aber wenn ich es danach anrufeos.kill() es gibt mirOSError: [Errno 10] No child processes.

Übrigens starte und stoppe ich den Unterprozess einer HTML-Vorlage mit zwei Formularen und die Programmlogik befindet sich in einer Django-Ansicht. Die Ausnahme wird in meinem Browser angezeigt, wenn sich meine Anwendung im Debug-Modus befindet. Es ist wahrscheinlich auch wichtig zu wissen, dass der von mir aufgerufene Subprozess (python manage.py crawlwebpages) selbst ruft einen anderen Unterprozess auf, nämlich eine Instanz eines Scrapy-Crawlers. Ich schreibe diepid dieser Scrapy-Instanz an diepidfile und das ist, was ich beenden möchte.

Hier ist der relevante Code:

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

Was kann ich machen? Vielen Dank!

BEARBEITEN:

Gemäßdie gute antwort gegeben durchJacek KoniecznyIch könnte mein Problem lösen, indem ich meinen Code in der Funktion ändere_stop_crawler(request) Zu dem Folgendem:

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

Antworten auf die Frage(2)

Ihre Antwort auf die Frage