2017-05-19 13 views
0

これは私が作成している関数です。プロセスの一部が1時間かかるので、リアルタイムで印刷するかどうかを示す1つの引数があります。私は同時にいくつかの副作用をしているので、エラーを発生させてすべてを止めるか、メインスクリプトを実行させるという別の引数があります。python popenを使って印刷したり、通信や戻りコードを保存する方法は?

もし私がprint_real_time Trueであれば、p.communicate()が緩んでいます iterからのすべてのプリントを変数に格納して返すことができましたが、どのようにしてstd outとstderr失敗したかどうかを確認する戻り値を取得しますか?あなたの問題へ

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_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 
関連する問題