2017-09-13 1 views
0

다음 코드를 사용하여 Python Popen 프로세스를 서로 간소화하려고 시도했습니다. Process는 인수 (stdout 또는 stdin이없는)가있는 프로세스를 나타내며 pipe 함수는이를 연결합니다. 나는 파이프 기능을 실행하면Python 파이프 라인 연결 시도 중`ValueError : 닫힌 파일에 대한 입출력 작업 '

def Process(parameters, *args, **kwargs): 
    """ 
    Represents a process that can be piped into another 
    """ 
    parameters = [str(p) for p in parameters] 

    # Partially apply the constructor, so we can handle the piping later 
    return functools.partial(subprocess.Popen, parameters, *args, **kwargs) 


def pipe(commands, stdin=None): 
    """ 
    Pipes a series of commands into each other 
    :param commands: An array of commands, each of which is an instance of Process 
    :param stdin: stdin to the first command 
    :param kwargs: Any extra arguments to pass to subprocess.Popen 
    :return: 
    """ 
    # Keep track of previous processes 
    processes = [] 

    # Each process's stdin is the stdout of the previous stage 
    for i, cmd in enumerate(commands): 
     if i == 0: 
      process = cmd(stdin=subprocess.PIPE, stdout=subprocess.PIPE) 
     else: 
      previous = processes[-1] 
      process = cmd(stdin=previous.stdout, stdout=subprocess.PIPE) 

      # Close stdout of previous command so we get SIGPIPE 
      previous.stdout.close() 

     processes.append(process) 

    first = processes[0] 
    final = processes[-1] 

    if first == final: 
     # If we only have one process, return its output 
     return first.communicate(stdin) 
    else: 
     # Pipe input into first process 
     first.communicate(stdin) 

     # Return Final process 
     return final.communicate() 

그러나, 다음과 같이 나는 previous.stdout.close()를 생략하면

ValueError: I/O operation on closed file 

특히,이 오류가 도망 간다 :

stdout, stderr = pipe([ 
    Process(['tr', 'n', '\\n']), 
    Process(['rev']), 
    Process(['wc', '-l']), 
], text) 

내가 오류가 발생합니다. 그러나 subprocess docs은 SIGPIPE가 작동하기를 원한다면 그것을 강력히 권장합니다.

내가 뭘 잘못하고 있니?

답변

0

stdout을 즉시 닫지 말고 끝에 닫아야합니다. 표준 출력이 여전히 활성화되어 있으므로

if first == final: 
    # If we only have one process, return its output 
    result = first.communicate(stdin) 
    first.stdout.close() 
    return first.communicate(stdin) 
else: 
    # Pipe input into first process 
    first.communicate(stdin) 

    # Return Final process 
    result = final.communicate() 
    for process in processes: 
     process.stdout.close() 
    return result 

한 번에 Popen 반환하기 때문에, 당신의 명령이 완료되지 않습니다.

+0

왜 [subprocess docs] (https://docs.python.org/2.7/library/subprocess.html#replacing-shell-pipeline)에서 즉시 닫습니까? – Miguel

+0

@Miguel 차이점은'dmesg'가 stdout으로 끝내고'tr'로 끝내지 않는다고 생각합니다. 그리고 특정 진행 상황에 대해 잘 모르겠습니다. 어쩌면 디버거를 사용하여이를 파악할 수 있습니다. – Sraw

관련 문제