저는 여러 명령을 실행 중입니다.이 명령은 Python 2.6을 실행하는 Linux 컴퓨터에서 병렬로 시간이 걸릴 수 있습니다.파이썬 subprocess.Popen & communicate()의 멀티 스레드 사용이 개선 되었습니까?
따라서 여러 개의 명령 그룹을 병렬 처리하고 실행 후 즉시 출력을 캡처하려면 subprocess.Popen
클래스와 process.communicate()
메서드를 사용했습니다.
def run_commands(commands, print_lock):
# this part runs in parallel.
outputs = []
for command in commands:
proc = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
output, unused_err = proc.communicate() # buffers the output
retcode = proc.poll() # ensures subprocess termination
outputs.append(output)
with print_lock: # print them at once (synchronized)
for output in outputs:
for line in output.splitlines():
print(line)
은 다른 곳에서 다음과 같이라고 :
processes = []
print_lock = Lock()
for ...:
commands = ... # a group of commands is generated, which takes some time.
processes.append(Thread(target=run_commands, args=(commands, print_lock)))
processes[-1].start()
for p in processes: p.join()
print('done.')
예상되는 결과는 명령 그룹의 각 출력은 한 번에 실행이 병렬로 수행하는 동안 표시되는 것입니다.
그러나 두 번째 출력 그룹 (물론 두 번째 스레드는 예약 비결정성으로 인해 변경됩니다)에서 줄 바꿈없이 각 줄에 인쇄 된 문자 수만큼 공간을 추가하기 시작합니다. 입력 에코가 꺼져 있습니다 - 터미널 상태가 "왜곡"또는 "크래시"입니다. (reset
쉘 명령을 실행하면 정상으로 복원됩니다.)
처음에는 '\r'
의 처리 이유를 찾으려했지만 그 이유가 아닙니다. 내 코드에서 볼 수 있듯이 splitlines()
을 사용하여 올바르게 처리했으며 repr()
기능을 출력에 적용했음을 확인했습니다.
이유는 stdout/stderr에 대해 Popen
및 communicate()
에 파이프를 동시 사용하는 것입니다. 파이썬 2.7에서 단축키 메서드 check_output
을 시도했지만 성공하지 못했습니다. 물론 모든 명령 실행 및 인쇄를 직렬화하면 위에 설명한 문제가 발생하지 않습니다.
Popen
과 communicate()
을 병렬로 처리하는 더 좋은 방법이 있습니까?
'.communicate()'는'Popen.wait()'을 호출하여 프로세스가 완료되도록합니다. 그러나'proc.poll()'은 프로세스 완료를 보장하지 않습니다. 프로세스가 완료되지 않은 경우'None'을 리턴합니다. 예를 들어 리눅스에서는'waitpid (pid, WNOHANG)'를 호출합니다. 'WNOHANG'을위한 문서에서는 : "waitpid() 함수는 상태가 pid에 의해 지정된 자식 프로세스 중 하나에 즉시 사용 가능하지 않으면 호출 스레드의 실행을 일시 중단하지 않습니다." http://www.mkssoftware.com/docs/man3/waitpid.3.asp – jfs
모든 프로세스를 병렬로 실행하고 그룹 내의 순서를 유지하는 프로세스 그룹별로 출력하는 스크립트는 다음과 같습니다. https://gist.github.com/717467 – jfs
Sebastian에 감사드립니다. 그러나 솔루션으로 문제가 완전히 해결되지 않았습니다. 파이썬의 서브 프로세스 구현과 동기화에서 버그로 보입니다. 최종 결과를 답으로 추가했습니다. – Achimnol