基于Raspberry Pi 3的Alexa Skill从Google Drive下载文件报错求助
解决Lambda函数中"Read-only file system"错误的方案
问题根源
你遇到的OSError: [Errno 30] Read-only file system错误,是因为AWS Lambda的运行环境默认只有/tmp目录具备可读写权限,其他目录(比如当前工作目录/var/task)都是只读的。你的代码尝试直接在当前目录创建abc.pdf文件,自然会触发这个错误。
第一步:修改文件保存路径到/tmp目录
把文件保存路径改为Lambda允许的临时目录/tmp,修改get_file函数里的文件名定义:
# 替换原来的filename定义 filename = os.path.join('/tmp', os.path.basename(urlparse(url).path))
同时,修复语音输出里的变量引用错误(你当前的代码里filename变量没有被正确插入到字符串中):
# 替换原来的speech_output speech_output = f'The file {os.path.basename(filename)} has been downloaded'
另外,你的代码在return时引用了未定义的reprompt_text,需要补充定义:
# 在get_file函数里添加reprompt_text的定义 reprompt_text = "" # 或者根据需求设置合适的提示文本
第二步:修复Google Drive下载的认证问题
注意:即使解决了文件系统的问题,你当前的Google Drive下载逻辑也大概率无法成功。因为https://drive.google.com/drive/my-drive/abc.pdf是网页链接,不是直接的文件下载链接,而且Google Drive不支持通过简单的auth=(username, password)方式进行认证。
如果你的文件是公开共享的,需要把链接转换成可直接下载的格式:
- 找到Google Drive文件的共享链接,格式通常是
https://drive.google.com/file/d/[FILE_ID]/view - 转换成下载链接:
https://drive.google.com/uc?export=download&id=[FILE_ID] - 把这个链接替换到你的代码里,不需要
auth参数,直接用requests.get(url)即可。
如果你的文件是私有文件,需要使用Google Drive API进行认证:
- 创建Google Cloud服务账号,生成密钥文件
- 在Lambda中加载密钥,使用
google-api-python-client库进行认证和文件下载(需要在Lambda层添加对应的依赖)
修改后的完整get_file函数示例
def get_file(intent, session): """ Grabs the files from the path that have to be downloaded """ card_title = intent['name'] session_attributes = {} should_end_session = True # 替换为正确的Google Drive直接下载链接 url = 'https://drive.google.com/uc?export=download&id=你的文件ID' filename = os.path.join('/tmp', os.path.basename(urlparse(url).path)) reprompt_text = "" try: r = requests.get(url) r.raise_for_status() # 捕获HTTP请求错误 with open(filename, 'wb') as out: for bits in r.iter_content(chunk_size=1024): out.write(bits) speech_output = f'The file {os.path.basename(filename)} has been downloaded successfully to Lambda\'s /tmp directory' except Exception as e: speech_output = f'Failed to download file: {str(e)}' return build_response(session_attributes, build_speechlet_response( card_title, speech_output, reprompt_text, should_end_session))
额外注意事项
- Lambda的
/tmp目录最大可用空间是512MB,且会话结束后(Lambda函数执行完成)该目录的内容可能会被清理,如果需要持久化文件,建议下载后上传到S3存储。 - 如果需要把文件下载到你的Raspberry Pi,Lambda本身无法直接操作Pi的文件系统,你需要让Lambda发送消息到Pi(比如通过MQTT、HTTP请求等),由Pi自己执行下载操作。
内容的提问来源于stack exchange,提问作者Seeker90
相关产品推荐
相关产品推荐

