2010-08-03 2 views
5

내가 병렬 (예를 들어 아래의 '수면'에 대한)python : 어린이를 죽이거나 성공을보고하는 간단한 방법?

  1. 전화 쉘 명령, 개인의 시작과 완료 및
  2. 것은 그들을 죽일 수에
  3. 보고 할 '죽일 -9 parent_process_pid '.

이미 많은 종류의 글들이 이미 있지만, 필자가 찾고있는 우아한 파이썬 해결책을 찾지 못한 것 같습니다. 나는 또한 파이썬에 익숙하지 않은 사람에게 상대적으로 읽기 쉬운 (그리고 짧다) 것을 유지하려고 노력하고있다.

내 방식까지 (아래 코드 참조)하고있다 : 명령의 시작과 완료를보고하는 래퍼 함수에서

  1. 풋 subprocess.call (unix_command).
  2. multiprocess.Process로 랩퍼 기능을 호출하십시오.
  3. 적절한 pid를 추적하여 전역으로 저장하고 signal_handler에서이를 삭제하십시오.

주기적으로 프로세스를 폴링하는 솔루션을 피하려고했지만 그 이유를 모르겠습니다.

더 좋은 방법이 있습니까?

import subprocess,multiprocessing,signal 
import sys,os,time 

def sigterm_handler(signal, frame): 
     print 'You killed me!' 
     for p in pids: 
       os.kill(p,9) 
     sys.exit(0) 

def sigint_handler(signal, frame): 
     print 'You pressed Ctrl+C!' 
     sys.exit(0) 

signal.signal(signal.SIGINT, sigint_handler) 
signal.signal(signal.SIGTERM, sigterm_handler) 

def f_wrapper(d): 
     print str(d) + " start" 
     p=subprocess.call(["sleep","100"]) 
     pids.append(p.pid) 
     print str(d) + " done" 

print "Starting to run things." 

pids=[] 

for i in range(5): 
     p=multiprocessing.Process(target=f_wrapper,args=(i,)) 
     p.daemon=True 
     p.start() 

print "Got things running ..." 

while pids: 
     print "Still working ..." 
     time.sleep(1) 
+8

주목받는 제목입니다. –

+1

파이썬이 아이들을 죽일 수 있다는 것을 몰랐습니다 ... –

+0

@ Zonda333 : 오, 물론. '__future__ import murder'에서. –

답변

4

subprocess.call 반환되면, 하위 프로세스가 완료 - 그리고 call의 반환 값은 하위 프로세스의 returncode. 따라서 리턴 코드를 목록 pids에 축적하면 (다중 프로세스가 추가 된 프로세스와 "주"프로세스간에 동기화되지 않고 리턴 코드 대신 프로세스 ID 인 것처럼 "012"로 표시됩니다) 잘못된.

'이 죽일 -9 parent_process_pid를'그들을 죽일 수 :

확실히 잘못 질문에 또 다른 것은 사양이다.

가능성 (즉 명시 적으로 을 지정하는 목적의) 신호를 가로 챌 수없는 부모 프로세스를 의미하기 때문에 - 나는 여기에 따라서 가짜 상상.

대신 multiprocessingthreading 사용해야

(각 "베이비 시터"스레드 또는 프로세스는 하위 프로세스를 기다리하지만, 본질적으로 아무것도하지 않는다, 왜 같은 가벼운 작업에 폐기물 처리 -?); 서브 프로세스를 시작하고 목록에 넣기 위해 .pid을 얻을 수 있도록 메인 스레드에서 suprocess.Process으로 호출하고 결과 프로세스 객체를 대기하는 보봇 (Babysitter) 스레드로 전달해야합니다 (보고가 완료되면 목록에서 제거합니다. 기본 스레드와 여러 베이비 시터 스레드가 모두 액세스 할 수 있으므로 하위 프로세스 ID 목록을 잠금으로 보호해야하며 주문할 필요가 없으므로 집합이 목록 (빠른 제거)보다 더 나은 선택 일 수 있습니다. 중복을 피하는 방법.버그가있을 수 있습니다 있도록

그래서, 약 (더 테스트, ;-) 난 당신의 코드를 변경하지 줄에 S/일이 같은 :

import subprocess, threading, signal 
import sys, time 

pobs = set() 
pobslock = threading.Lock() 
def numpobs(): 
    with pobslock: 
     return len(pobs) 

def sigterm_handler(signal, frame): 
    print 'You killed me!' 
    with pobslock: 
     for p in pobs: p.kill() 
    sys.exit(0) 

def sigint_handler(signal, frame): 
    print 'You pressed Ctrl+C!' 
    sys.exit(0) 

signal.signal(signal.SIGINT, sigint_handler) 
signal.signal(signal.SIGTERM, sigterm_handler) 

def f_wrapper(d, p): 
    print d, 'start', p.pid 
    rc = p.wait() 
    with pobslock: 
     pobs.remove(p) 
    print d, 'done, rc =', rc 

print "Starting to run things." 

for i in range(5): 
    p = subprocess.Popen(['sleep', '100']) 
    with pobslock: 
     pobs.add(p) 
    t = threading.Thread(target=f_wrapper, args=(i, p)) 
    t.daemon=True 
    t.start() 

print "Got things running ..." 

while numpobs(): 
    print "Still working ..." 
    time.sleep(1) 
+0

감사합니다. 매우 도움이됩니다. 나는 이것을 정리하면 다시 게시 할 것이다! – mathtick

+0

@mathtick, 오신 것을 환영합니다! 나는 A 코드를 편집하여 대략적으로 코드가 가장 잘 구조화 된 것을 볼 수있는 방법을 보여주었습니다. –

+0

http://speculation.org/garrick/kill-9.html 이것은 나에게 좋은 교훈이었습니다. 나는 내가 처음 리눅스 박스를 만졌을 때 "-9"버릇을 발견했다고 생각한다. – mathtick

2

아래 (코드) 나를 위해 작동하는 것 같다이 코드, 커맨드 라인에서 "top"이나 ctrl-c로 죽이는 것. Alex의 제안에서 나온 유일한 진정한 변화는 subprocess.Process를 subprocess.Popen 호출로 대체하는 것이 었습니다 (저는 subprocess.Process가 있다고 생각하지 않습니다).

여기 코드는 어떻게 든 stdout을 잠그면 향상되어 프로세스간에 겹치는 부분이 인쇄되지 않을 수 있습니다.

import subprocess, threading, signal 
import sys, time 

pobs = set()       # set to hold the active-process objects 
pobslock = threading.Lock()  # a Lock object to make sure only one at a time can modify pobs 

def numpobs(): 
     with pobslock: 
       return len(pobs) 

# signal handlers 
def sigterm_handler(signal, frame): 
     print 'You killed me! I will take care of the children.' 
     with pobslock: 
       for p in pobs: p.kill() 
     sys.exit(0) 

def sigint_handler(signal, frame): 
     print 'You pressed Ctrl+C! The children will be dealt with automatically.' 
     sys.exit(0) 

signal.signal(signal.SIGINT, sigint_handler) 
signal.signal(signal.SIGTERM, sigterm_handler) 


# a function to watch processes 
def p_watch(d, p): 
     print d, 'start', p.pid 
     rc = p.wait() 
     with pobslock: 
       pobs.remove(p) 
     print d, 'done, rc =', rc 


# the main code 
print "Starting to run things ..." 
for i in range(5): 
     p = subprocess.Popen(['sleep', '4']) 
     with pobslock: 
       pobs.add(p) 
     # create and start a "daemon" to watch and report the process p. 
     t = threading.Thread(target=p_watch, args=(i, p)) 
     t.daemon=True 
     t.start() 

print "Got things running ..." 
while numpobs(): 
     print "Still working ..." 
     time.sleep(1) 
+0

당신은 바로 subprocess.Process - thinko에 대해 유감스럽게 생각합니다 .- 지금 수정하여 A를 수정하십시오. –

관련 문제