如何在脱离Shell的进程中使用Python的subprocess.run()
解决Python脚本后台运行时subprocess调用失败的问题
问题根源
你的脚本前台正常但后台执行失败,主要是以下几个原因导致:
capture_output=True引发的缓冲区阻塞:后台运行时,子进程的stdout/stderr被捕获但未读取,缓冲区占满后会卡住进程。- 环境变量差异:后台运行环境的PATH可能不包含
ffmpeg的路径,导致找不到可执行文件。 - 工作目录不一致:后台启动脚本时,当前工作目录可能不是存放.wav文件的目录,
glob('*.wav')无法匹配到文件。
修复方案
1. 替换capture_output=True,避免缓冲区阻塞
将输出定向到空设备,既不会因缓冲区满阻塞进程,也不会产生冗余输出:
from glob import glob import subprocess as sp for w in sorted(glob('*.wav')): sp.run(['ffmpeg', '-y', '-i', w, '-f', 'mp4', '-vn', '-acodec', 'libfdk_aac', '-ac', '2', '-ab', '196k', f'{w}.m4a'], stdout=sp.DEVNULL, stderr=sp.DEVNULL)
如果需要保留转码日志,可将输出定向到文件:
from glob import glob import subprocess as sp for w in sorted(glob('*.wav')): with open('transcode_log.txt', 'a', encoding='utf-8') as log_file: sp.run(['ffmpeg', '-y', '-i', w, '-f', 'mp4', '-vn', '-acodec', 'libfdk_aac', '-ac', '2', '-ab', '196k', f'{w}.m4a'], stdout=log_file, stderr=log_file)
2. 使用ffmpeg的绝对路径调用
后台环境的PATH可能不包含ffmpeg路径,直接写ffmpeg会找不到程序,换成绝对路径(例如Linux下/usr/bin/ffmpeg,Windows下C:\\ffmpeg\\bin\\ffmpeg.exe):
sp.run(['/usr/bin/ffmpeg', '-y', '-i', w, ...])
3. 指定绝对路径的工作目录
不要依赖当前工作目录,改用绝对路径定位.wav文件,确保后台运行时能正确匹配:
from pathlib import Path import subprocess as sp # 替换为你的音频文件所在绝对路径 audio_dir = Path('/home/your_username/audio_files') for w in sorted(audio_dir.glob('*.wav')): output_file = audio_dir / f'{w.stem}.m4a' sp.run(['/usr/bin/ffmpeg', '-y', '-i', str(w), '-f', 'mp4', '-vn', '-acodec', 'libfdk_aac', '-ac', '2', '-ab', '196k', str(output_file)], stdout=sp.DEVNULL, stderr=sp.DEVNULL)
4. 后台启动时指定工作目录
如果不想修改代码,启动脚本时先切换到目标目录再后台运行:
cd /path/to/your/audio/files && python script.py &
内容的提问来源于stack exchange,提问作者sambler
相关产品推荐
相关产品推荐

