代码之家  ›  专栏  ›  技术社区  ›  O.rka

如何检查子进程中的popen是否引发错误

  •  1
  • O.rka  · 技术社区  · 6 年前

    我正在编写一个管道,它使用一系列特定顺序的bash调用。

    如何判断我的命令是否引发错误?

    例如,我正在运行一个带有子进程的Java程序,在这个过程出错时它不会警告我或退出。

    里面有东西吗 subprocess 或者在我的 process 具有此实用程序的对象?

    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    process.wait()
    

    当我尝试来自 Python: "subprocess.Popen" check for success and errors 我得到以下错误:

    In [6]: subprocess.check_call(process)
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-6-f8f8752a245f> in <module>
    ----> 1 subprocess.check_call(process)
    
    ~/anaconda/envs/µ_env/lib/python3.6/subprocess.py in check_call(*popenargs, **kwargs)
        284     check_call(["ls", "-l"])
        285     """
    --> 286     retcode = call(*popenargs, **kwargs)
        287     if retcode:
        288         cmd = kwargs.get("args")
    
    ~/anaconda/envs/µ_env/lib/python3.6/subprocess.py in call(timeout, *popenargs, **kwargs)
        265     retcode = call(["ls", "-l"])
        266     """
    --> 267     with Popen(*popenargs, **kwargs) as p:
        268         try:
        269             return p.wait(timeout=timeout)
    
    ~/anaconda/envs/µ_env/lib/python3.6/subprocess.py in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, encoding, errors)
        707                                 c2pread, c2pwrite,
        708                                 errread, errwrite,
    --> 709                                 restore_signals, start_new_session)
        710         except:
        711             # Cleanup if the child failed starting.
    
    ~/anaconda/envs/µ_env/lib/python3.6/subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session)
       1218                 args = [args]
       1219             else:
    -> 1220                 args = list(args)
       1221
       1222             if shell:
    
    TypeError: 'Popen' object is not iterable
    
    In [7]: subprocess.check_output(process)
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-7-0ec9e7eac1c2> in <module>
    ----> 1 subprocess.check_output(process)
    
    ~/anaconda/envs/µ_env/lib/python3.6/subprocess.py in check_output(timeout, *popenargs, **kwargs)
        334
        335     return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    --> 336                **kwargs).stdout
        337
        338
    
    ~/anaconda/envs/µ_env/lib/python3.6/subprocess.py in run(input, timeout, check, *popenargs, **kwargs)
        401         kwargs['stdin'] = PIPE
        402
    --> 403     with Popen(*popenargs, **kwargs) as process:
        404         try:
        405             stdout, stderr = process.communicate(input, timeout=timeout)
    
    ~/anaconda/envs/µ_env/lib/python3.6/subprocess.py in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, encoding, errors)
        707                                 c2pread, c2pwrite,
        708                                 errread, errwrite,
    --> 709                                 restore_signals, start_new_session)
        710         except:
        711             # Cleanup if the child failed starting.
    
    ~/anaconda/envs/µ_env/lib/python3.6/subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session)
       1218                 args = [args]
       1219             else:
    -> 1220                 args = list(args)
       1221
       1222             if shell:
    
    TypeError: 'Popen' object is not iterable
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   James    6 年前

    两个 check_call check_output 应该传递一个命令系统要运行的命令列表(与发送到的命令列表相同 Popen )这两个调用都是阻塞调用,这意味着Python将等待它们完成运行更多代码。

    使用 波彭 将命令列表发送到命令系统,但不会阻止Python代码的进一步执行。您可以使用 .poll 方法 波彭 对象,或者可以使用 .communicate 它将返回标准输出和标准错误流的元组。

    假设您需要执行命令的结果,并且该命令将正确地向错误流报告错误,则可以使用:

    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = process.communicate()
    
    if err:
         print('The process raised an error:', err.decode())
    

    以下是一些例子:

    使用 波彭 :

    import subprocess
    
    # first a command that works correctly
    proc = subprocess.Popen(['ls', '-a'], , stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = proc.communicate()
    if not err:
        print('--No errors--\n', out.decode())
    else:
        print('--Error--\n', err.decode())
    
    # prints:
    --No errors--
    anaconda3
    Desktop
    Documents
    Downloads
    
    # next a command generates and error, the `-w` switch is invalid
    proc = subprocess.Popen(['ls', '-w'], , stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = proc.communicate()
    if not err:
        print('--No errors--\n', out.decode())
    else:
        print('--Error--\n', err.decode())
    
    # prints:
    --Error--
     ls: option requires an argument -- 'w'
    Try 'ls --help' for more information.
    

    使用 检查调用

    检查调用 如果来自命令系统的返回代码不是0,将引发python异常。

    # first with a working command:
    ret_code = subprocess.check_call(['ls', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    ret_code
    # returns:
    0
    
    # and now with the command that generates an error:
    ret_code = subprocess.check_call(['ls', '-w'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    
    # raises an exception:
    ---------------------------------------------------------------------------
    CalledProcessError                        Traceback (most recent call last)
    <ipython-input-25-3cd5107991a2> in <module>()
    ----> 1 ret_code = subprocess.check_call(['ls', '-w'], stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE)
    
    ~/anaconda3/lib/python3.6/subprocess.py in check_call(*popenargs, **kwargs)
        289         if cmd is None:
        290             cmd = popenargs[0]
    --> 291         raise CalledProcessError(retcode, cmd)
        292     return 0
        293
    
    CalledProcessError: Command '['ls', '-w']' returned non-zero exit status 2.
    

    要处理异常,请使用 try/except 块。

    try:
        ret_code = subprocess.check_call(['ls', '-w'], stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE)
    except subprocess.CalledProcessError as e:
        ret_code = e.returncode
        print('An error occurred.  Error code:', ret_code)
    
    # prints:
    An error occurred.  Error code: 2
    

    使用 校验输出

    校验输出 非常类似于 检查调用 如果来自命令系统的返回代码不是0,那么它将引发一个python异常。但是,如果返回代码为0,它将返回标准输出流中的输出。

    # just with the error process this time
    try:
        ret_code = subprocess.check_output(['ls', '-w'], stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE)
    except subprocess.CalledProcessError as e:
        ret_code = e.returncode
        print('An error occurred.  Error code:', ret_code)
    
    # prints:
    An error occurred.  Error code: 2
    
    推荐文章