如何找出当子使用os.kill后已终止()?(How to find out when subpro

2019-08-02 18:44发布

我有开始使用一个子Python程序(准确地说,Django应用程序) subprocess.Popen 。 由于我的应用程序的体系结构的限制,我不能使用Popen.terminate()终止子和Popen.poll()来检查时,进程已经终止。 这是因为我不能抱着一个变量的启动子的参考。

相反,我要的进程id写pid到文件pidfile子进程启动时。 当我想阻止子,我打开这个pidfile并使用os.kill(pid, signal.SIGTERM)停止它。

我的问题是:我如何才能找到当子真的结束? 使用signal.SIGTERM它需要大约1-2分钟,最后终止调用后os.kill() 首先,我认为os.waitpid()将成为这个任务的正确的事情,但是当我后把它os.kill()它给了我OSError: [Errno 10] No child processes

顺便说一句,我开始并使用两种形式从HTML模板停止子和程序逻辑是一个Django视图中。 当我的应用程序是在调试模式下的异常被显示在我的浏览器。 这可能也很重要,要知道,我在我的观点(也称子python manage.py crawlwebpages )本身调用另一个子流程,即Scrapy履带的一个实例。 我写的pid此Scrapy实例到的pidfile ,这是我要终止的。

下面是相关的代码:

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

我能做什么? 非常感谢你!

编辑:

据伟大的答案给出亚切克Konieczny ,我可以通过改变功能我的代码解决我的问题_stop_crawler(request)于以下内容:

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

Answer 1:

检查通常的方式如果一个进程仍在运行是杀死()将其与信号“0”。 当然这并不能运行工作,并提出了一个OSError有例外, errno=ESRCH如果进程不存在。

[jajcus@lolek ~]$ sleep 1000 &
[1] 2405
[jajcus@lolek ~]$ python
Python 2.7.3 (default, May 11 2012, 11:57:22) 
[GCC 4.6.3 20120315 (release)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.kill(2405, 0)
>>> os.kill(2405, 15)
>>> os.kill(2405, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 3] No such process

但是无论合适可能的调用者应该留在这个过程被称为的父母和使用wait()函数族来处理其终止。 这就是Popen对象一样。



Answer 2:

我的解决方案将是把控制定子处理的中间过程。

所以,你的web请求(这似乎都在不同的进程发生 - 由于并行?)告诉控制程序启动给定的程序,看它; 只要需要,他们问的状态是什么。

这个过程将在最简单的情况下,是打开一个UNIX域套接字(一个TCP / IP套接字也同样可以),听它的过程。 “网络程序”连接到它,发送到启动请求,并且取回一个唯一的ID。 然后,它可以使用这个ID,使新系统的过程进一步查询。

另外,也给出了自己的ID(或它使用的不是ID可言,如果只能是一个流程),所以不必保留一些变量ID周围。



文章来源: How to find out when subprocess has terminated after using os.kill()?