2015-01-18 3 views
0

내 파이썬 코드를 파이썬에서 함수 호출을 종료하는 것은 다음과 같이 진행됩니다 등등n 초 후

def a(): 
    ... 
    ... 
    subprocess.call() 
    ... 
    ... 

def b(): 
    ... 
    ... 

하고 있습니다.

내 작업 :
1) 3 초 내에 subprocess.call() 반환, 내 실행이 순간을 subprocess.call() 수익을 계속해야합니다.
2) subprocess.call()이 3 초 이내에 반환되지 않으면 subprocess.call()을 종료해야하고 3 초 후에 실행을 계속해야합니다.
3) subprocess.call()이 반환되거나 3 초가 끝날 때까지 추가 실행이 발생하지 않아야합니다.

이것은 스레드로 수행 할 수 있지만 어떻게 수행 할 수 있습니까? 실제 코드의

관련 부분은 다음과 같이 진행됩니다

... 
cmd = ["gcc", "-O2", srcname, "-o", execname];  
p = subprocess.Popen(cmd,stderr=errfile)//compiling C program 
... 
... 
inputfile=open(input,'w') 
inputfile.write(scanf_elements) 
inputfile.close() 
inputfile=open(input,'r') 
tempfile=open(temp,'w') 
subprocess.call(["./"+execname,str(commandline_argument)],stdin=inputfile,stdout=tempfile); //executing C program 
tempfile.close() 
inputfile.close() 
... 
... 

내가 컴파일하고 파이썬을 사용하여 C 프로그램을 실행하려합니다. subprocess.call()을 사용하여 C 프로그램을 실행할 때 C 프로그램에 무한 루프가 포함되어 있다고 가정하면 subprocess.call()은 3 초 후에 종료되어야하고 프로그램은 계속 진행되어야합니다. subprocess.call()이 강제 종료되었거나 성공적으로 실행 되었기 때문에 다음 코드에서 메시지를 적절하게 인쇄 할 수 있는지 여부를 알 수 있어야합니다.

백엔드 gcc는 Linux 용입니다. 당신이 call (당신이 gcc를 실행하는 동일한 방식) 대신 Popen 생성자에 전화를 변환하고자하는 경우

+0

import signal import subprocess class Alarm(Exception): pass def alarm_handler(signum, frame): raise Alarm # start process process = subprocess.Popen(*your_subprocess_call_args) # set signal handler signal.signal(signal.SIGALRM, alarm_handler) signal.alarm(3) # produce SIGALRM in 3 seconds try: process.wait() # wait for the process to finish signal.alarm(0) # cancel alarm except Alarm: # subprocess does not return within 3 seconds process.terminate() # terminate subprocess process.wait() 

여기에 휴대용 threading.Timer() 기반 솔루션입니다 [타임 아웃이있는 서브 프로세스]의 복제본 (http : // st ackoverflow.com/questions/1191374/subprocess-with-timeout) – jfs

+0

관련 : [중단없이 파이썬에서 프로세스 출력 읽기를 중지 하시겠습니까?] (http://stackoverflow.com/a/4418891/4279) – jfs

답변

1

:

import subprocess 
import threading 
import time 


def process_tree_kill(process_pid): 
    subprocess.call(['taskkill', '/F', '/T', '/PID', process_pid]) 

def main(): 
    cmd = ["gcc", "-O2", "a.c", "-o", "a"]; 
    p = subprocess.Popen(cmd) 
    p.wait() 
    print "Compiled" 
    start = time.time() 

    process = subprocess.Popen("a",shell=True) 
    print(str(process.pid)) 

    # terminate process in timeout seconds 
    timeout = 3 # seconds 
    timer = threading.Timer(timeout, process_tree_kill,[str(process.pid)]) 
    timer.start() 

    process.wait() 
    timer.cancel() 

    elapsed = (time.time() - start) 
    print elapsed 

if __name__=="__main__": 
    main() 
+0

1.'Popen (cmd) .wait()'대신'call (cmd)'를 쓸 수 있습니다. 2.'쉘을 드롭 = TRUE '(A)는 popen이 실행 파일을 (프로그램이 발견하는 방법을 서로 다른 규칙이) 찾을 수없는 경우 전체 경로 (디렉토리와 파일 확장자를) 제공합니다. (b)'process.terminate'는'kill_process_tree' 대신에 충분합니다 (부모 쉘 프로세스 없음, C 자식 프로세스 만) – jfs

0

이 접근하는 다음 방법 중 하나는 3 초 정도 기다리 서브 프로세스를 폴링하고 행동을 기반으로 걸릴 것입니다 해당 returncode 속성이 여전히 None인지 여부. 다음과 같은 매우 인위적인 예를 고려해

import sys 
import time 
import logging 
import subprocess 

logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO) 

if __name__ == '__main__': 
    logging.info('Main context started') 
    procCmd = 'sleep %d' % int(sys.argv[1]) 
    proc = subprocess.Popen(procCmd.split()) 

    time.sleep(3) 
    if proc.poll() is None: 
    logging.warning('Child process has not ended yet, terminating now') 
    proc.terminate() 
    else: 
    logging.info('Child process ended normally: return code = %s' % str(proc.returncode)) 

    logging.info('Main context doing other things now') 
    time.sleep(5) 
    logging.info('Main context ended') 

을 그리고 이것은 자식 프로세스가 3 초 없습니다 이내에 완료 여부에 따라 다른 로깅 출력 결과 :이 방법은 위의 항상 3을 대기하는

$ python parent.py 1 
2015-01-18 07:00:56,639 INFO Main context started 
2015-01-18 07:00:59,645 INFO Child process ended normally: return code = 0 
2015-01-18 07:00:59,645 INFO Main context doing other things now 
2015-01-18 07:01:04,651 INFO Main context ended 
$ python parent.py 10 
2015-01-18 07:01:05,951 INFO Main context started 
2015-01-18 07:01:08,957 WARNING Child process has not ended yet, terminating now 
2015-01-18 07:01:08,957 INFO Main context doing other things now 
2015-01-18 07:01:13,962 INFO Main context ended 

주 서브 프로세스가 그보다 더 빨리 완료 되더라도 몇 초가 걸립니다. 위의 내용을 다른 동작을 원할 경우 하위 프로세스를 계속 폴링하는 루프와 같은 것으로 변환 할 수 있습니다. 얼마나 많은 시간이 경과했는지 추적하면됩니다.

+0

코드를 사용하려고했습니다. 내 모든 제약 조건을 충족시키지 만 할 수는 없었습니다. 문제는 내가 proc = subprocess.Popen을 쓰레드에 넣어야했지만 파이썬에 익숙하지 않았기 때문에 외부에서 (상태 검사를 위해) 접근 할 수 없다는 것이 었습니다. 나는 작동하는 코드를 썼다. 그것을 참조하고 thread.exit() 또는 다른 문제를 사용하는 데 문제가 있는지 여부를 알 수 있습니까? – user8109

+0

지금 등록하십시오. – user8109

-1
#!/usr/bin/python 

import thread 
import threading 
import time 
import subprocess 
import os 

ret=-1 

def b(arg): 
    global ret 
    ret=subprocess.call(arg,shell=True); 

thread.start_new_thread(b,("echo abcd",)) 
start = time.time() 


while (not (ret == 0)) and ((time.time() - start)<=3): 
    pass 

if (not (ret == 0)) : 
    print "failed" 
    elapsed = (time.time() - start) 
    print elapsed 
    thread.exit() 

elif (ret == 0):#ran before 3 sec 
    print "successful" 
    elapsed = (time.time() - start) 
    print elapsed 

나는 위의 모든 코드를 작성하고 작동하는 코드를 작성했습니다. 링크 https://docs.python.org/2/library/thread.html 메시지 :

thread.exit() SystemExit 예외를 발생시킵니다. 잡히지 않으면 스레드가 자동으로 종료됩니다.

그래서 고아 프로세스, 차단 된 리소스 등의 문제가 없어야한다고 생각해주십시오.

+0

'thread '모듈을 직접 사용하지 말고 대신'threading' 모듈을 사용하십시오. – jfs

+0

이전에 스레딩 모듈을 사용했지만이 모듈을 사용하여 스레드를 효과적으로 죽이는 방법을 모르겠습니다. 내가 지금 게시 한 코드에서 thread1을 죽일 방법을 제안 해 주시겠습니까? – user8109

+0

당신은 스레드를 죽이지 않습니다. 스레드를 사용하려면; Threading.Timer' 기반의 솔루션을 사용하십시오. * 이미 여러 번 제공 한 링크 (http://stackoverflow.com/a/4418891/4279)의 솔루션과 비슷합니다. 당신의 경우는 더 간단합니다. 단지'deque() '로 출력을 읽는 대신'process.wait()'를 호출하십시오. – jfs

1

내 작업 :
1) 만약 subprocess.call() 3 초 내에 반환, 내 실행이 순간 subprocess.call() 반환을 계속해야합니다.
2) subprocess.call()이 3 초 이내에 반환되지 않으면 subprocess.call()이 종료되어야하고 3 초 후에 실행이 이되어야합니다.
3) subprocess.call()이 반환하거나 3 초가 끝날 때까지 추가 실행이 발생하지 않아야합니다.

* nix에서 스크립트에

, 당신은 signal.alarm()-based solution 사용할 수 있습니다 아래의 코드는 일을 마지막으로

import subprocess 
import threading 

# start process 
process = subprocess.Popen(*your_subprocess_call_args) 

# terminate process in 3 seconds 
def terminate(): 
    if process.poll() is None: 
     try: 
      process.terminate() 
     except EnvironmentError: 
      pass # ignore 

timer = threading.Timer(3, terminate) 
timer.start() 
process.wait() 
timer.cancel() 
+0

문제는 귀하의 링크에 따라 process.stdout.readline()이 반환되지 않으면 차단 될 수 있다는 점입니다. 하지만이 기능도 필요합니다. – user8109

+0

@ user8109 : 출력이 질문의 파일로 리디렉션됩니다. 'process.stdout'는이 경우'None'입니다. 출력을 읽어야 할 경우 quesiton *을 업데이트하고 실제로 사용하는 코드를 제공하십시오. – jfs

+0

코드에 파일의 내용보다 많은 scanf 문이 포함되어 있으면 C 코드가 멈추고 코드도 중단됩니다. 내가 맞습니까? – user8109