복붙노트

[PYTHON] Python, Popen 및 select - 프로세스 종료 또는 대기 시간 기다림

PYTHON

Python, Popen 및 select - 프로세스 종료 또는 대기 시간 기다림

나는 다음을 사용하여 서브 프로세스를 실행한다.

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

이 하위 프로세스는 stderr의 오류와 함께 즉시 종료되거나 계속 실행 중일 수 있습니다. 나는이 조건들 중 하나를 감지하기를 원합니다 - 후자는 몇 초를 기다려야합니다.

나는 이것을 시도했다 :

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

하지만 그냥 반환 :

  ([],[],[])

어느 쪽의 조건이라도. 내가 무엇을 할 수 있을지?

해결법

  1. ==============================

    1.Popen.Poll () 메서드를 사용해 보셨습니까? 당신은 단지 이것을 할 수 있습니다 :

    Popen.Poll () 메서드를 사용해 보셨습니까? 당신은 단지 이것을 할 수 있습니다 :

    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에서 일반적으로 읽으려는 것이므로 읽는 데 사용할 수있는 것이 언제 있는지 알고 싶습니다 (예 : 실패 사례).

    이게 도움이 되길 바란다.

  2. ==============================

    2.이것은 내가 생각해내는 것입니다. 필요할 때 작동하고 thep 프로세스에서 시간 초과가 필요하지 않지만 세미 - 바쁜 루프가 있습니다.

    이것은 내가 생각해내는 것입니다. 필요할 때 작동하고 thep 프로세스에서 시간 초과가 필요하지 않지만 세미 - 바쁜 루프가 있습니다.

    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)
    
  3. ==============================

    3.다음은 좋은 예입니다.

    다음은 좋은 예입니다.

    from threading import Timer
    from subprocess import Popen, PIPE
    
    def kill_proc():
        proc.kill()
    
    proc = Popen("ping 127.0.0.1", shell=True)
    t = Timer(60, kill_proc)
    t.start()
    proc.wait()
    
  4. ==============================

    4.선택과 수면을 사용하는 것은별로 의미가 없습니다. select (또는 임의의 커널 폴링 메커니즘)는 본질적으로 비동기 프로그래밍에 유용하지만 예제는 동기식입니다. 따라서 정상적인 블로킹 방식을 사용하도록 코드를 다시 작성하거나 Twisted를 사용하는 것이 좋습니다.

    선택과 수면을 사용하는 것은별로 의미가 없습니다. select (또는 임의의 커널 폴링 메커니즘)는 본질적으로 비동기 프로그래밍에 유용하지만 예제는 동기식입니다. 따라서 정상적인 블로킹 방식을 사용하도록 코드를 다시 작성하거나 Twisted를 사용하는 것이 좋습니다.

    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을 작성하여 Twisted로 이것을하는 더 안전한 방법이 있습니다 :

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

  5. ==============================

    5.위의 설명에서 말했듯이, 매번 출력물을 조정하고 명령을 다시 실행하면 다음 작업을 수행 할 수 있습니까?

    위의 설명에서 말했듯이, 매번 출력물을 조정하고 명령을 다시 실행하면 다음 작업을 수행 할 수 있습니까?

    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를 계속 실행하면서 잠재적으로 중복되는 프로세스라는 것입니다.

  6. ==============================

    6.

    import subprocess as sp
    
    try:
        sp.check_call(["/subprocess"], timeout=10,
                      stdin=sp.DEVNULL, stdout=sp.DEVNULL, stderr=sp.DEVNULL)
    except sp.TimeoutError:
        # timeout (the subprocess is killed at this point)
    except sp.CalledProcessError:
        # subprocess failed before timeout
    else:
        # subprocess ended successfully before timeout
    

    TimeoutExpired 문서를 참조하십시오.

  7. ==============================

    7.이것은 Evan의 대답에 대한 의역이지만 다음 사항을 고려합니다.

    이것은 Evan의 대답에 대한 의역이지만 다음 사항을 고려합니다.

  8. from https://stackoverflow.com/questions/337863/python-popen-and-select-waiting-for-a-process-to-terminate-or-a-timeout by cc-by-sa and MIT license