Choregraphe 2.8中NAO6虚拟机器人运行Python脚本打开file.json报找不到文件错误
Choregraphe 2.8 环境下json文件路径识别异常解决方案
问题背景
- 运行配置:Choregraphe 2.8 + NAO6虚拟机器人
- 运行状态:已导入外部Python脚本,除json文件读取环节外,其余脚本功能运行正常
- 触发报错:调用文件读取逻辑时抛出固定报错:
...\choregraphe\...\data\PackageManager\apps\.lastUploadedChoregrapheBehavior\behavior_1/..\read_json.py", line 9, in open_json with open('file.json', encoding = 'utf-8', mode='r') as json_file: IOError: [Errno 2] No such file or directory: 'file.json'
- 已尝试方案:采用sys.path插入路径的跨文件导入方法、其余所有跨文件访问方案,均触发相同报错
现有核心代码片段
read_json.py 原有代码
class JsonData(): def open_json(self): with open('file.json', encoding = 'utf-8', mode='r') as json_file: self.json_data = json.load(json_file) return self.json_data def get_param(self, parameter): # open json file to access data self.open_json() # get the key values from json file if parameter == "test": name = self.json_data["Name"] return name
attachment_file.py 原有导入逻辑(省略无关业务代码)
#other parts of the code are not included... def onLoad(self): self.framemanager = ALProxy("ALFrameManager") def onInput_onStart(self): self.folderName = self.framemanager.getBehaviorPath(self.behaviorId) + self.getParameter("File name") if (self.folderName) not in sys.path: sys.path.insert(0, self.folderName) self.onStopped() def onUnload(self): if (self.folderName) in sys.path: sys.path.remove(self.folderName)
内置box原有调用逻辑
def onInput_onStart(self): import read_json self.a = read_json.JsonData() json_data = self.a.show_param("test") #string output self.tts.say(json_data)
问题根因
现有路径逻辑的两个核心认知偏差导致报错:
sys.path的作用是帮助Python定位可导入的.py模块文件,插入路径的操作能让你正常importread_json.py,但open()函数读取普通文件时,不会自动遍历sys.path下的路径搜索目标文件,只会检索当前进程的工作目录下的相对路径文件- Choregraphe运行行为脚本时,进程默认工作目录是机器人端的行为上传缓存目录(即报错信息中显示的
.lastUploadedChoregrapheBehavior路径),代码里写的相对路径'file.json'根本没有指向你存放json文件的行为资源目录
可落地修复方案
方案1:透传json文件绝对路径(改动最可控,推荐)
不要在脚本里写死相对路径,将行为资源目录的绝对路径在模块间传递,从根源避免路径查找偏差:
- 修改内置box的
onInput_onStart逻辑:
def onInput_onStart(self): import sys import os from naoqi import ALProxy # 复用框架接口获取当前行为的根目录绝对路径 framemanager = ALProxy("ALFrameManager") behavior_root_path = framemanager.getBehaviorPath(self.behaviorId) # 拼接json文件的完整绝对路径,不使用相对路径 json_full_path = os.path.join(behavior_root_path, "file.json") # 将行为根目录加入模块搜索路径,确保能正常导入read_json.py if behavior_root_path not in sys.path: sys.path.insert(0, behavior_root_path) import read_json self.a = read_json.JsonData() # 调用方法时传入json文件的完整路径 json_data = self.a.get_param("test", json_full_path) self.tts.say(json_data)
- 修改
read_json.py的方法,移除硬编码的相对路径:
import json class JsonData(): def open_json(self, json_file_path): # 使用传入的绝对路径打开文件,不依赖相对路径查找 with open(json_file_path, encoding='utf-8', mode='r') as json_file: self.json_data = json.load(json_file) return self.json_data def get_param(self, parameter, json_file_path): self.open_json(json_file_path) if parameter == "test": name = self.json_data["Name"] return name
方案2:调整进程工作目录(改动量最小,适配原有代码)
如果不想修改read_json.py的现有结构,可以在导入模块前,将Python进程的工作目录切换到json文件的存放路径,让原有相对路径的open()逻辑能正常工作:
def onInput_onStart(self): import sys import os from naoqi import ALProxy framemanager = ALProxy("ALFrameManager") behavior_root_path = framemanager.getBehaviorPath(self.behaviorId) # 将进程工作目录切换到json文件所在的行为根目录 os.chdir(behavior_root_path) # 原有导入、调用逻辑完全保留即可 if behavior_root_path not in sys.path: sys.path.insert(0, behavior_root_path) import read_json self.a = read_json.JsonData() # 注意:原代码中调用的方法名为show_param,但类中定义的是get_param,记得统一方法名避免属性报错 json_data = self.a.get_param("test") self.tts.say(json_data)
注意事项
- json文件必须放在当前行为包的资源目录下,确保
getBehaviorPath(self.behaviorId)能正确定位到文件位置,不要将文件存在Choregraphe安装目录、机器人系统根目录等非行为目录下 - 虚拟机器人环境下运行时,要确认json文件已经和行为包一同上传到虚拟机器人的文件系统,不要仅存在本地Choregraphe的编辑目录中
- 原有代码存在方法名拼写不一致的问题:调用时写的是
show_param,类中定义的是get_param,需要统一方法名,否则会触发额外的属性不存在报错
内容的提问来源于stack exchange,提问作者MahlaNasr
相关产品推荐
相关产品推荐

