FastAPI后台启动子进程报错:'function' object has no attribute 'submit'
解决AttributeError: 'function' object has no attribute 'submit'问题
错误根源
你把loop.run_in_executor的参数顺序搞反了:
run_in_executor的第一个参数是执行器对象(可选,留空则用默认线程池),第二个参数才是要在执行器中运行的函数,后续是该函数的参数。- 你错误地将
subprocess.run作为第一个参数传入,导致asyncio把它当成执行器调用submit方法,但subprocess.run是普通函数,没有这个方法,因此触发报错。
另外还有两个潜在问题:
subprocess.run本身会阻塞直到子进程完成,返回的是CompletedProcess对象,不是Popen对象,调用process.communicate()会报错。- 未捕获子进程输出,无法正确获取执行日志或错误信息。
修正步骤
- 调整
run_in_executor的参数顺序,将执行器参数设为None(使用默认线程池),再传入subprocess.run和它的参数。 - 给
subprocess.run添加capture_output=True和text=True参数,方便捕获并读取输出内容。 - 删除错误的
process.communicate()调用,直接通过process.stdout和process.stderr获取输出。
修正后的完整代码
import asyncio import os import subprocess from fastapi import APIRouter router = APIRouter() temp_dir = "./temp" # 根据实际情况修改路径 @router.get("/testdo") async def do(): asyncio.create_task(editing()) return {"message": "Video processing started in the background!"} async def editing(): recordingFile = os.path.join(temp_dir, "test.mp4") webFile = os.path.join(temp_dir, "keeptest.mp4") ffmpeg_change_bitrate = ['ffmpeg', '-i', recordingFile, '-b:v', '5M', '-y', webFile] loop = asyncio.get_event_loop() # 修正run_in_executor参数顺序,添加捕获输出的参数 process = await loop.run_in_executor( None, subprocess.run, ffmpeg_change_bitrate, capture_output=True, text=True ) if process.returncode == 0: print('Completed Editing') print(f"FFmpeg output: {process.stdout}") else: print(f'Error occurred: {process.stderr}') print('It will take more x seconds') await asyncio.sleep(20) # 模拟上传S3的处理时间 print('It took x seconds') print('Completed Editing, it took x minutes')
额外说明
- 如果需要自定义线程池,可以提前创建
ThreadPoolExecutor实例,传入run_in_executor的第一个参数,例如:from concurrent.futures import ThreadPoolExecutor executor = ThreadPoolExecutor(max_workers=2) process = await loop.run_in_executor(executor, subprocess.run, ...) - 确保
temp_dir路径存在,且ffmpeg命令能在系统PATH中找到,或者使用完整路径调用(如'C:/ffmpeg/bin/ffmpeg.exe')。
内容的提问来源于stack exchange,提问作者Zaid
相关产品推荐
相关产品推荐

