Python - проблемы с созданием функции тайм-аута (kill subprocess) - PullRequest
0 голосов
/ 06 января 2012

Я нуждаюсь в вашей поддержке в моей маленькой программе, которая создает подпроцесс, здесь 10-пиновый запрос, и должна быть уничтожена заданным значением времени ожидания (5). Этот пример не удался. Можете ли вы дать мне подсказку?

С уважением. Stefan

Выход:

Traceback (most recent call last):
File "./nwcheck.py.work", line 146, in <module>
MyCheck().check().exit()
File "./nwcheck.py.work", line 80, in check
output = process.communicate()
File "/usr/lib/python2.6/subprocess.py", line 701, in communicate
return self._communicate(input)
File "/usr/lib/python2.6/subprocess.py", line 1199, in _communicate
rlist, wlist, xlist = select.select(read_set, write_set, [])
File "./nwcheck.py.work", line 29, in alarm_handler
raise alarm
TypeError: exceptions must be old-style classes or derived from BaseException, not   builtin_function_or_method

КОД:

def check(self):

    class Alarm(Exception):
        pass

    def alarm_handler(signum, frame):
        raise alarm

    def get_process_children(pid):
        p = Popen('ps --no-headers -o pid --ppid %d' % pid, shell = True,
                   stdout = PIPE, stderr = PIPE)
        stdout, stderr = p.communicate()
        return [int(p) for p in stdout.split()]
    timeout = 5
    args2 = [
            'ping',
            'localhost',
            '-c 10',
            ]
    process = subprocess.Popen(args2, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env={'LANG':'de_DE@euro'})
    processpid = process.pid
    print processpid
    if timeout != -1:
        signal(SIGALRM, alarm_handler)
        alarm(timeout)
        print 'in timeout abfrage'
    try:
        ## catch stdout and stderr
        output = process.communicate()
        if timeout != -1:
            alarm(0)
            print 'in timeout abfrage 2'
    except Alarm:
        pids = [process.pid]
        print pids
        if kill_tree:
            pids.extend(get_process_children(process.pid))
        for pid in pids:
        # process might have died before getting to this line
        # so wrap to avoid OSError: no such process
            try:
                kill(pid, SIGKILL)
            except OSError:
                pass
        return -9, '', ''

    # Return a response
    return output

Ответы [ 3 ]

2 голосов
/ 06 января 2012

Вы, вероятно, должны использовать исключение вместо тревоги:

class AlarmException(Exception): 
    pass 

...

    def alarm_handler(signum, frame):
        raise AlarmException()

Кроме того, не забывайте, что трубы могут переполняться .Если процесс выдаст слишком много (> 64 КБ в некоторых Linux) для stderr и / или stdout, программа будет заблокирована.

0 голосов
/ 06 января 2012

Ваше исключение называется Alarm, но вы повышаете alarm.Python чувствителен к регистру.

Возможно, вы захотите переименовать Alarm во что-то более наглядное.Простое имя, например AlarmException или AlarmError, сделает код более понятным.

0 голосов
/ 06 января 2012

подпроцесс может быть убит:

import os
os.kill(process.pid, signal.SIGKILL)

или может быть:

from subprocess import Popen
Popen.kill()

или:

from subprocess import Popen
Popen.terminate()

См. Это: http://docs.python.org/library/subprocess.html#popen-objects

...