You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI路由调用subprocess执行Python脚本未完成,返回非零状态1

问题分析与解决

核心问题原因

你遇到的报错根本原因是脚本里的fig.show()调用。终端运行时你处于有桌面环境的会话,fig.show()能正常弹出图形窗口,但FastAPI服务运行的环境(尤其是生产环境或无桌面的服务器环境)没有图形显示上下文(DISPLAY环境变量不存在),fig.show()尝试打开GUI窗口失败,直接导致脚本返回非零退出码1——这和GeoJSON加载无关,哪怕你移除后续代码,只要保留这行就会报错。

快速修复步骤

  • 删除/注释fig.show():脚本是后台生成图片用的,完全不需要弹出显示窗口,这行属于冗余代码。
  • 统一使用绝对路径:subprocess的工作目录不一定和你终端运行时一致,相对路径极易导致文件找不到问题。可以用__file__动态计算绝对路径:
    import os
    # 获取脚本所在目录的绝对路径
    script_dir = os.path.dirname(os.path.abspath(__file__))
    # 拼接图片保存路径
    map_save_path = os.path.join(script_dir, '../images/map.png')
    fig.write_image(map_save_path)
    # 拼接GeoJSON文件路径
    geojson_path = os.path.join(script_dir, '../geojsons/guam.geojson')
    with open(geojson_path) as f:
        guam_geojson = json.load(f)
    
    FastAPI路由里的script_path和FileResponse的路径也建议换成绝对路径,避免工作目录不一致的坑。
  • 检查subprocess参数:你代码里的subprocess.run传了json参数,但脚本里没处理命令行参数,如果不需要传参就直接删掉,否则要在脚本里用sys.argv接收。

更优实现方案:直接调用函数而非subprocess

用subprocess调用脚本是低效且易出问题的方式,更好的做法是把脚本逻辑封装成函数,在FastAPI中直接导入调用:

  1. 改造get_map.py为模块,封装生成图片的函数:

    # maps/get_map.py
    import ssl
    ssl._create_default_https_context = ssl._create_unverified_context
    import os
    import json
    import plotly.graph_objects as go
    import pandas as pd
    
    def generate_maps():
        script_dir = os.path.dirname(os.path.abspath(__file__))
        # 生成第一个地图
        df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2011_february_us_airport_traffic.csv')
        df['text'] = df['airport'] + ' ' + df['city'] + ', ' + df['state'] + ' Arrivals: ' + df['cnt'].astype(str)
        
        fig = go.Figure(data=go.Scattergeo(
                lon=df['long'],
                lat=df['lat'],
                text=df['text'],
                mode='markers',
                marker_color=df['cnt'],
            ))
        fig.update_layout(
                title='Most trafficked US airports<br>(Hover for airport names)',
                geo_scope='usa',
            )
        map_path = os.path.join(script_dir, '../images/map.png')
        fig.write_image(map_path)
        
        # 加载GeoJSON并生成关岛地图
        geojson_path = os.path.join(script_dir, '../geojsons/guam.geojson')
        with open(geojson_path) as f:
            guam_geojson = json.load(f)
        
        # 这里补充生成usa_guam地图的逻辑
        # ...
        us_guam_save_path = os.path.join(script_dir, '../images/us_guam_map.png')
        usa_guam.save(us_guam_save_path)
        
        return us_guam_save_path
    
  2. 在FastAPI路由中直接调用该函数:

    from fastapi import FastAPI
    from fastapi.responses import FileResponse
    from maps.get_map import generate_maps
    
    app = FastAPI()
    
    @app.get('/getMap')
    def get_map(): 
        try: 
            map_path = generate_maps()
            return FileResponse(map_path)
        except Exception as e: 
            return {"message": "Error", "error": str(e)}         
    

这种方式避免了subprocess的上下文切换、环境不一致等问题,代码更易维护,执行效率也更高。

内容的提问来源于stack exchange,提问作者bestfirstsearch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:23:35