Python, Popen и выбор - ожидающий процесса для завершения или тайм-аут

22
задан Lie Ryan 25 September 2011 в 20:09
поделиться

4 ответа

Вы попытались использовать Popen. Опрос () метод. Вы могли просто сделать это:

p = subprocess.Popen("subprocess", 
                   stdout=subprocess.PIPE, 
                   stderr=subprocess.PIPE, 
                   stdin=subprocess.PIPE)

time.sleep(SECONDS_TO_WAIT)
retcode = p.poll()
if retcode is not None:
   # process has terminated

Это заставит Вас всегда ожидать 10 секунд, но если бы случай возникновения отказов редок, это было бы амортизировано по всем случаям успеха.

<час>

Редактирование:

Как насчет:

t_nought = time.time()
seconds_passed = 0

while(p.poll() is not None and seconds_passed < 10):
    seconds_passed = time.time() - t_nought

if seconds_passed >= 10:
   #TIMED OUT

Это имеет уродство того, чтобы быть активным ожиданием, но я думаю, что оно выполняет то, что Вы хотите.

Дополнительно рассмотрение избранной документации вызова снова я думаю, что можно хотеть изменить его следующим образом:

SECONDS_TO_WAIT = 10
  select.select([p.stderr], 
                [], 
                [p.stdout, p.stderr],
                SECONDS_TO_WAIT)

, Так как Вы обычно хотели бы читать из stderr, Вы хотите знать, когда он имеет что-то в наличии для чтения (т.е. случай возникновения отказов).

я надеюсь, что это помогает.

15
ответ дан Alejo 29 November 2019 в 05:21
поделиться

Используя выбор и сон действительно не имеет большого количества смысла. выбор (или любой механизм опроса ядра) по сути полезен для асинхронного программирования, но Ваш пример синхронен. Так или перепишите свой код, чтобы использовать нормальный вид блокирования или рассмотреть использование Скрученный:

from twisted.internet.utils import getProcessOutputAndValue
from twisted.internet import reactor    

def stop(r):
    reactor.stop()
def eb(reason):
    reason.printTraceback()
def cb(result):
    stdout, stderr, exitcode = result
    # do something
getProcessOutputAndValue('/bin/someproc', []
    ).addCallback(cb).addErrback(eb).addBoth(stop)
reactor.run()

Кстати, существует более безопасный способ сделать это со Скрученным путем записи собственного ProcessProtocol:

http://twistedmatrix.com/projects/core/documentation/howto/process.html

2
ответ дан 29 November 2019 в 05:21
поделиться

Если, поскольку Вы сказали в комментариях выше, Вы просто настраиваете вывод каждый раз и повторно выполняете команду, что-то хотело бы следующую работу?

from threading import Timer
import subprocess

WAIT_TIME = 10.0

def check_cmd(cmd):
    p = subprocess.Popen(cmd,
        stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE)
    def _check():
        if p.poll()!=0:
            print cmd+" did not quit within the given time period."

    # check whether the given process has exited WAIT_TIME
    # seconds from now
    Timer(WAIT_TIME, _check).start()

check_cmd('echo')
check_cmd('python')

код выше, когда выполнено, выводы:

python did not quit within the given time period.

единственный недостаток вышеупомянутого кода, о котором я могу думать, является потенциально перекрывающимися процессами, поскольку Вы продолжаете управлять check_cmd.

1
ответ дан shsmurfy 29 November 2019 в 05:21
поделиться

Вот что я придумал. Работает, когда вам нужно и не нужно тайм-аут для процесса p, но с полузанятым циклом.

def runCmd(cmd, timeout=None):
    '''
    Will execute a command, read the output and return it back.

    @param cmd: command to execute
    @param timeout: process timeout in seconds
    @return: a tuple of three: first stdout, then stderr, then exit code
    @raise OSError: on missing command or if a timeout was reached
    '''

    ph_out = None # process output
    ph_err = None # stderr
    ph_ret = None # return code

    p = subprocess.Popen(cmd, shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    # if timeout is not set wait for process to complete
    if not timeout:
        ph_ret = p.wait()
    else:
        fin_time = time.time() + timeout
        while p.poll() == None and fin_time > time.time():
            time.sleep(1)

        # if timeout reached, raise an exception
        if fin_time < time.time():

            # starting 2.6 subprocess has a kill() method which is preferable
            # p.kill()
            os.kill(p.pid, signal.SIGKILL)
            raise OSError("Process timeout has been reached")

        ph_ret = p.returncode


    ph_out, ph_err = p.communicate()

    return (ph_out, ph_err, ph_ret)
8
ответ дан 29 November 2019 в 05:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: