2017-05-19 13 views
0

這是我創建的函數,我有一個參數可以指示打印實時或不打印,因爲某些過程需要一個小時。因爲我在同一時間分幾個子進程,另一個提出錯誤並停止一切的參數,或者讓主腳本運行。如何使用python popen打印並存儲通信和返回代碼?

,但如果我這樣做print_real_time真的,我鬆p.communicate() 我可以一切從ITER的打印存儲在一個變量和返回,但我怎麼整理性病出來,和標準錯誤,並得到返回值,看看是否失敗或不?

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然後用列表的內容來生成標準輸出數據串。如果print_real_time不是True,則改爲使用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 

作爲一個方面說明,我也勸你嘗試將程序改寫爲使用shell=TruePopen電話。可能需要將輸入cmd預處理爲基本命令和參數列表,但使用shell=True通常被認爲是不好的主意。

+0

aja我們把錯誤也放在這樣的列表中 – 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