部署至Google Cloud Run的Docker Flask出现文件找不到错误求助
问题:Google Cloud Run容器中/tmp文件无法找到,无法存储文件供后续调用
错误信息
[Errno 2] No such file or directory '/tmp/my_file_20230319_163330.mp3'
报错触发于mix_audios函数的这一行:
text_mp3_file = AudioSegment.from_file(txt_file)
无法读取create_file函数中写入到/tmp目录的文件。
核心代码片段
def create_audio(text): audio_length = 120 * 15 file_name = None text = text overlay_type = None # best is 10 overlay_volume = 15 # default rate is 200 # best is 300 rate = 250 speaker = None text_mp3_file = create_file(text, rate, speaker) audio_file = mix_audios(text_mp3_file, audio_length, file_name, overlay_type, overlay_volume) return send_file(audio_file, as_attachment=True) def create_file(text, rate, speaker): engine = pyttsx3.init() file_name = f'/tmp/my_file_{datetime.now().strftime(DATE_FORMAT)}.mp3' engine.save_to_file(text, file_name) engine.runAndWait() engine.stop() return file_name def mix_audios(txt_file, audio_length, filename, overlay_type, overlay_volume): text_mp3_file = AudioSegment.from_file(txt_file) overlay = AudioSegment.from_file(overlay_file(overlay_type)) multiplier = math.ceil(audio_length / overlay.duration_seconds) overlay = overlay * multiplier overlay = overlay[:(audio_length * 1000)] combined = overlay.overlay(text_mp3_file, gain_during_overlay=overlay_volume, loop=True) file_name = f'/tmp/my_file_{datetime.now().strftime(DATE_FORMAT)}.mp3' combined.export(file_name, format='mp3') return file_name
配置文件
app.yaml
runtime: python310 env: flex entrypoint: gunicorn -b :$PORT main:app runtime_config: python_version: 3.10 manual_scaling: instances: 1 resources: cpu: 1 memory_gb: 0.5 disk_size_gb: 10
Dockerfile
FROM python:3.10-slim ENV PYTHONUNBUFFERED True ENV APP_HOME /app WORKDIR $APP_HOME COPY . ./ RUN python3 --version RUN apt-get update && apt-get upgrade -y RUN apt-get install espeak -y RUN apt-get install ffmpeg -y RUN apt-get install gunicorn -y RUN apt-get install libespeak1 -y RUN apt-get install portaudio19-dev -y RUN apt-get install python3-pyaudio -y RUN echo "Installed dependencies" RUN pip install --upgrade pip RUN pip install --no-cache-dir -r requirements.txt RUN pip list CMD gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
问题分析与解决方案
核心原因
- 文件名冲突:
create_file和mix_audios使用完全相同的时间戳生成文件名,若请求处理速度快,两个函数的文件名会重复,可能出现文件未写完就被读取,或刚生成就被覆盖的情况。 - Cloud Run临时目录特性:Cloud Run的/tmp是内存文件系统,虽然同请求内文件不会被清理,但如果pyttsx3写入文件时出现权限、资源不足等问题,会导致文件未生成。
- 资源限制:当前配置仅0.5GB内存,音频处理可能因内存不足导致文件写入失败。
解决方案
1. 避免文件名冲突
使用UUID生成唯一文件名,彻底解决时间戳重复问题:
import uuid # create_file函数中修改文件名生成逻辑 file_name = f'/tmp/text_mp3_{uuid.uuid4()}.mp3' # mix_audios函数中修改文件名生成逻辑 file_name = f'/tmp/combined_mp3_{uuid.uuid4()}.mp3'
2. 验证文件写入状态
在create_file返回文件名前,添加文件存在性检查并打印日志,便于排查问题:
import os import logging def create_file(text, rate, speaker): engine = pyttsx3.init() file_name = f'/tmp/text_mp3_{uuid.uuid4()}.mp3' engine.save_to_file(text, file_name) engine.runAndWait() engine.stop() # 检查文件是否生成并打印日志 if not os.path.exists(file_name): logging.error(f"Failed to create file: {file_name}") raise FileNotFoundError(f"File {file_name} was not created") logging.info(f"Created file: {file_name}, size: {os.path.getsize(file_name)} bytes") return file_name
可在Cloud Run控制台查看日志,确认文件是否成功生成。
3. 替换临时目录为应用内路径
避免系统/tmp的潜在权限问题,在应用目录下创建专属临时文件夹:
# 应用初始化时创建临时目录 import os TEMP_DIR = os.path.join(os.environ.get('APP_HOME', '/app'), 'temp') os.makedirs(TEMP_DIR, exist_ok=True) # 在create_file和mix_audios中使用该目录 file_name = os.path.join(TEMP_DIR, f'text_mp3_{uuid.uuid4()}.mp3')
4. 调整Cloud Run资源配置
增加内存配额,避免因资源不足导致文件写入失败:
# 修改app.yaml中的resources部分 resources: cpu: 1 memory_gb: 1 disk_size_gb: 10
5. 验证容器内espeak可用性
在Dockerfile中添加espeak测试命令,确保依赖正常工作:
RUN espeak "test" --stdout > /tmp/test.mp3 && ls -l /tmp/test.mp3
内容的提问来源于stack exchange,提问作者mgorb
相关产品推荐
相关产品推荐

