为何subprocess调用的py中的raise没起作用?

背景

我有一个脚本A需要通过subprocess在另外一个脚本B中被调用。在脚本A中有一个raise语句来捕获异常【单独运行这个脚本会正常报错】,但脚本B在调用的时候并不会捕获到这个异常,返回状态码依旧是0,不懂为什么?可能哪里我没注意到或者没理解一些原理嘛。。。

部分代码

由于一些原因,代码不能完全展示,我只展示部分...

# A.py
...

def get_rid_lonlat(self):
        need_json_list = self.need_json.split(",")
        print("need_json_list:{}".format(need_json_list))
        # json_data_list: [rid_subid_trajs.json,rid_subid_trajsoverlap.json,spot_json.json]
        json_data_list = []
        for file_name in need_json_list:
            file_path = os.path.join(self.input_road_data, file_name)
            if os.path.exists(file_path):
                json_data = self.read_json(file_path)
                json_data_list.append(json_data)
            else:
                raise FileNotFoundError(file_path)  # raise exception

...
# B.py

import os
import argparse
import subprocess


def run_vis_rid_draw(
    data_name: str, 
    hdmap_path: str, 
    road_path: str, 
    vis_road_path: str, 
    code_abs_path: str = 'A.py'
) -> bool:
    vis_code_abs_path: str = os.path.join(hdmap_path, code_abs_path)
    road_data_name: str = 'Road_{name}'.format(name=data_name)
    road_data_path: str = os.path.join(road_path, road_data_name)
    vis_road_data_path: str = os.path.join(vis_road_path, road_data_name)
    vis_log_path: str = os.path.join(vis_road_data_path, 'road_vis_map.log')
    
    # create vis_road_data_path
    os.makedirs(vis_road_data_path, exist_ok=True)
    
    cmds: list = ['echo', 'xxxxxx', '|', 'sudo', '-S', 'sh', '-c',
                "'python3", vis_code_abs_path, '-i', road_data_path, 
                '-o', vis_road_data_path, '|', 'tee', f"{vis_log_path}'"]
    
    cmds_str: str = " ".join(cmds)
    print('cmd: ', cmds_str)
    return_flag = subprocess.run(cmds_str, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)

    if return_flag.returncode:
        print(f'Error: {return_flag.returncode} => {return_flag.stderr.decode()}')
    
    else:
        print(f'Normal: {return_flag.returncode} => {return_flag.stdout.decode()}')


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Execute the task of drawing map.')
    parser.add_argument('-i', '--data_name', help='data name',
                        default="example")
    parser.add_argument('-p', '--hdmap_path', help='hdmap path',
                        default='./')
    parser.add_argument('-r', '--raw_path', help='raw path',
                        default='./')
    parser.add_argument('-w', '--road_path', help='road path',
                        default='./')
    parser.add_argument('-v', '--vis_road_path', help='vis road path',
                        default='./')
    
    args = parser.parse_args()

    run_vis_rid_draw(args.data_name, args.hdmap_path, args.road_path, args.vis_road_path)
错误信息
# A.py

need_json_list:['rid_subid_trajs.json', 'rid_subid_trajsoverlap.json', 'spot_json.json']
Traceback (most recent call last):
  File "A.py", line 301, in <module>
    rm.run()
  File "A.py", line 200, in run
    rid_lonlat_dict, rid_num_dict = self.get_rid_lonlat()
  File "A.py", line 76, in get_rid_lonlat
    raise FileNotFoundError(file_path)
FileNotFoundError: xxx/rid_subid_trajs.json
# B.py
Normal: 0 => need_json_list:['rid_subid_trajs.json', 'rid_subid_trajsoverlap.json', 'spot_json.json']

可以看到A的报错,B并没抓取到,返回状态码还是0。。。所以请教各位一下。。。

阅读 2.2k
2 个回答

因为子进程引发异常 不会影响主进程

两个进程不可混为一谈。进程间的通信就是靠退出状态识别成功失败的。不同进程之间,没有异常这一说。
要判断状态 ,进程a要用相应的退出码和b 沟通。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题