问题来源: 为了支持模型的切换功能,拟通过调用不同模型路径下的predict.py方法来实现。这就涉及到调用外部py文件。调用外部py文件,有多种方式:
方法一:sys.path
1 import sys 2 sys.path.insert(0, modelPath) # 设置该目录拥有最高优先级 3 import predict
问题1:不符合python的PEP-8规范(即import语句应放在代码的最前面),可参考这篇给出的解决方案:
问题2:使用sys.path时,在程序运行过程中始终有效,每次使用后应注意及时删除已添加的路径。
1 # 定义 2 class add_path: 3 def __init__(self, path): 4 self.path = path 5 6 def __enter__(self): 7 sys.path.insert(0, self.path) 8 9 def __exit__(self, exc_type, exc_value, traceback): 10 try: 11 sys.path.remove(self.path) 12 except ValueError: 13 pass
1 # 使用 2 with add_path(modelPath): 3 import predict 4 XXXX
问题2-1:但进一步在真实的使用中发现,尽管我们在sys.path中删除了对应的路径,下次import predict时仍然会延续上一次的引入结果。这是因为sys.modules缓存路径(python在import module前,先会去sys.modules看看曾经有没有导入过这个模块)如果已经导入过就不会再从sys.path中重复读取,所以尽管我们已经改变了sys.path的内容,import predict仍然维持第一次的引入内容。
方案1:(已解决)解决方法是尝试删除sys.modules中的缓存内容
1 class add_path: 2 def __init__(self, path): 3 self.path = path 4 5 def __enter__(self): 6 sys.path.insert(0, self.path) 7 8 def __exit__(self, exc_type, exc_value, traceback): 9 try: 10 sys.path.remove(self.path) 11 # modules中的缓存名称与import的名称一致,可直接删除对应的缓存 12 # (但前提是该import仅在这一处使用) 13 if "predict" in sys.modules: 14 del sys.modules['predict'] 15 except ValueError: 16 pass
方案2:(未实现)引入多进程,每次调用完成后杀死进程,进程推出时会自动清空缓存。
另外一个思路是,考虑到对于sys.path的修改会在程序执行结束时失效,可以考虑开一个独立的进程引入模型包实现抽取功能,抽取结束后杀死进程。 方法二:使用 python 标准库 importlib 加载特定路径 参考stackoverflow链接,试了下发现这种方法只能导入一个python文件。遗留问题:如何导入一个目录1 # 导入指定python文件 2 def load_package_from_path(pkg_path: str) -> ModuleType: 3 """ 4 ref: https://stackoverflow.com/a/50395128 5 """ 6 name = basename(pkg_path) 7 8 spec = util.spec_from_file_location(name, pkg_path) 9 module = util.module_from_spec(spec) 10 sys.modules[spec.name] = module 11 spec.loader.exec_module(module) 12 13 return module
参考:
标签:__,python,解决方案,self,py,sys,import,path From: https://www.cnblogs.com/fresh-star/p/17024413.html