2012-12-17 2 views
2

여러 파이핑 단계가 포함 된 Python에서 유닉스 시스템에서 실행될 명령을 컴파일 중입니다. 예컨대 :Python에서 유닉스 용 파이프 명령을 검사하는 중 오류가 발생했습니다.

grep foo myfile | cmd1 | cmd2 > output 

이들은 myfile에서 그들 foo이 항목에 대한 일련의 변환에 해당합니다. 때로는 os.system에 의해 실행될 명령으로, 다른 경우에는 subprocess 모듈을 사용하여 명령을 구성합니다.

파이썬에서 파이프의 각 부분에 대해 어떻게 오류를 검사 할 수 있습니까? 예를 들어 99 %의 경우 foomyfile에 있고 나머지 파이프가 작동합니다. 그러나 어떤 이유로 든 myfile이 존재하지만 foo 항목이 없으면 빈 파일을 파이프하고 나머지 명령에 비어 있지 않은 입력이 필요하므로 나머지 파이프가 끊어집니다. 이렇게하면 중간 단계가 실패했음을 알지 못해 파손 된 파이프의 출력 만 표시되기 때문에 디버그하기가 어렵습니다.

파이썬에서 중간 단계 오류 검사 파이프를 만드는 방법이 있습니까? 예 : 그 파이프의 grep 부분에 실제로 출력이 포함되어 있는지 확인하십시오. grep의 출력에 cmd1 출력도 일부 출력을 포함하고 있습니까? 감사.

+0

이 작업을 수행하는 가장 쉬운 방법은 일을하는 것입니다 기본적으로 파이썬에서. OS와 파이썬에서 앞뒤로 전화를 걸면 처음에는 대개 피하는 여분의 변수와 복잡성이 생깁니다. –

+0

그래서 외부 명령을 호출해야한다면 파이썬에서 어떻게 할 수 있습니까? 내가 아는 유일한 방법은''하위 프로세스 ''입니다.나는 파이썬에서 호출하는 모든 명령을 다시 쓸 수 없다. – user248237dfsf

+2

bash에서 PIPESTATUS 변수가있다. 가능한 경우 사용하라. 그렇지 않으면 sr2222와 같은 python에서 제안합니다 - 파이프 설정, 리다이렉트 된 입력 출력으로 프로그램 시작, 종료 상태 확인, 그 문제는 무엇입니까? 언급 한 모듈도 stdin/stdout/stderr을 매개 변수로 사용합니다! – loreb

답변

0

내 접근 방식은 Python 2.6 Linux에서 테스트되었습니다.

a.Define 다음과 같은 방법 기본적으로

def test_run_command_pipestatus(self): 
    # the exit $PIPESTATUS is the return code of "exit 2". The default return code is the return code of last command in the pipe 
    return_code, out, err = run_command("exit 2 | tail -n 1; exit $PIPESTATUS") 
    print "return_code = %d" %return_code 
    print out 
    print err 
    self.assertEqual(2, return_code) 
0

대부분은 당신이 필요로하는 모든 중요한 정보를 가지고 Mingjiang시의 대답은, 같은에서 b.Use 방법

def run_command(command): 
    p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    out, err = p.communicate() 
    return (p.returncode, out, err) 

하지만, 추가 기능없이 문제를 해결할 수 있습니다. (파이썬 2.7.12와 3.5.2에서 테스트)

$ PIPESTATUS는 sh에 존재하지 않으므로, 배포판에 bash (예 : 우분투 dash을 사용합니다). 배열이므로 배열처럼 사용하는 것이 좋습니다.

communicate() 대신 을 사용하는 것이 좋습니다. 따라서 처리하기 전에 전체 출력을 메모리에로드하는 대신 작은 버퍼로 읽을 때 사용하십시오.

그래서 당신이 할 필요가있다 :

  • 문자열이 아닌 인수
  • 사용 쉘에 대한 목록을 사용한다 = TRUE
  • 사용 실행 = "/ 빈/bash는"

코드 :

p = subprocess.Popen("false | true; exit ${PIPESTATUS[0]}", shell=True, executable='/bin/bash', stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

# at this point you do your filtering, eg. using p.stdout.readinto(buf) 

p.wait() 
if p.returncode != 0: 
    # handle it here 
관련 문제