2017-05-19 11 views
0

이것은 내가 작성하는 함수입니다. 프로세스의 시간이 한 시간이 걸리므로 실시간 인쇄 여부를 알 수있는 인수가 하나 있습니다. 그리고 나는 동시에 여러 번 subprocessing하고 있기 때문에 오류를 일으키고 모든 것을 멈추게하거나 또는 메인 스크립트를 돌리게하는 또 다른 주장이된다. 내가 print_real_time 진정한 할 경우python popen을 사용하여 통신 및 반환 코드를 인쇄하고 저장하는 방법은 무엇입니까?

하지만, 나는 변수에 ITER의 모든 지문을 저장하고 그것을 반환 할 수) 합니다 (p.communicate을 풀어하지만, 내가 어떻게 위해 표준을 배치해야합니까, 그리고 표준 에러가 , 반환 값을 얻어 실패가 발생했는지 여부를 확인하십시오. print_real_timeTrue 된 후 표준 출력 데이터 문자열을 생성하는 목록의 내용을 사용할 때

def launch_subprocess_cmd(command_to_lunch, cwd=None, print_real_time=False, raise_errors=True): 
""" 
for a given command line will lunch that as a subprocess 
:param command_to_lunch: string 
:param print_real_time: boolean 
:param cwd: the folder path from where the command should be run. 
:param raise_errors: boolean if the return code of the subprocess is different than 0 raise an error an stop all scripts. 
         else the main script will keep running and can access the third return value of this function and decide what to do with it. 
:return: list com return the stdout and the stderr of the Popen subprocess. 
""" 
if cwd is None: 
    p = subprocess.Popen(command_to_lunch, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) 
else: 
    p = subprocess.Popen(command_to_lunch, cwd=cwd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) 

if print_real_time is True: 
    for i in iter(p.stdout.readline, b''): 
     print i 

com = p.communicate() 
if raise_errors is True: 
    if p.returncode != 0: 
     raise ValueError("\n\nSubprocess fail: \n" + "Error captures: \n" + "stdout:\n" + com[0] + "\nstderr:\n" + com[1] + "\n") 
# com[0] is std_out, com[1] is std_err and p.return code is if the subprocess was successful or not with a int number 
return com[0], com[1], p.returncode 

감사들 =)

답변

1

문제에 대한 가능한 해결책은 목록의 표준 출력 스트림을 저장하는 것입니다. print_real_timeTrue이 아닌 경우 com[0]의 콘텐츠를 사용하십시오. 보조 노트로

def launch_subprocess_cmd(cmd, cwd=None, print_real_time=False, raise_errors=True): 
    """ 
    for a given command line will lunch that as a subprocess 
    :param cmd: string 
    :param print_real_time: boolean 
    :param cwd: the folder path from where the command should be run. 
    :param raise_errors: boolean if the return code of the subprocess is different 
         than 0 raise an error an stop all scripts else 
         the main script will keep running and can access the third 
         return value of this function and decide what to do with it. 
    :return: list com return the stdout and the stderr of the Popen subprocess. 
    """ 
    if cwd is None: 
     p = subprocess.Popen(cmd, stderr=subprocess.PIPE, 
          stdout=subprocess.PIPE, shell=True) 
    else: 
     p = subprocess.Popen(cmd, cwd=cwd, stderr=subprocess.PIPE, 
          stdout=subprocess.PIPE, shell=True) 

    stdout_list = [] 
    if print_real_time is True: 
     for i in iter(p.stdout.readline, b''): 
      stdout_list.append(i) 
      print i 

    com = p.communicate() 
    stdout_data = "".join(stdout_list) if print_real_time is True else com[0] 

    if raise_errors is True: 
     if p.returncode != 0: 
      raise ValueError("\n\nSubprocess fail: \n" + "Error captures: \n" + 
          "stdout:\n" + stdout_data + "\nstderr:\n" + 
          com[1] + "\n") 
    # stdout_data is stdout, com[1] is stderr and 
    # p.return code is if the subprocess was successful or not with a int number 
    return stdout_data, com[1], p.returncode 

, 나는 당신의 Popen 전화에 사용 shell=True 하지에 프로그램을 다시 시도 할 것을 촉구도있다. 기본 명령과 인수 목록에 cmd 입력을 전처리해야 할 수도 있지만 일반적으로 shell=True을 사용하는 것은 좋지 않습니다.

+0

우리는 다음과 같은 목록에도 오류를 넣습니다. – pelos

0
launch_subprocess_cmd(command_to_lunch, cwd=None, print_real_time=False, raise_errors=True): 
if cwd is None: 
    p = subprocess.Popen(command_to_lunch, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) 
else: 
    p = subprocess.Popen(command_to_lunch, cwd=cwd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) 

stdout_list = [] 
errout_list = [] 
if print_real_time is True: 
    for i in iter(p.stdout.readline, b''): 
     stdout_list.append(i) 
     print i 
    for j in iter(p.stderr.readline, b''): 
     errout_list.append(j) 
     print j 

com = p.communicate() 
if print_real_time is True: 
    stdout_data = "".join(stdout_list) 
    std_err_data = "".join(errout_list) 
else: 
    stdout_data = com[0] 
    std_err_data = com[1] 

if raise_errors is True: 
    if p.returncode != 0: 
     raise ValueError("\n\npopen fail:\n" + command_to_lunch + "\nError:\n" + "Error captures:\n" + "stdout:\n" + stdout_data + "\nstderr:\n" + std_err_data + "\n") 
# com[0] is out, com[1] is errors and p.return code is if it fail or not 
return stdout_data, std_err_data, p.returncode