模块在调用文件旁边时获取ModuleNotFoundError-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

模块在调用文件旁边时获取ModuleNotFoundError

is大龙 2020-03-21 11:52:07 897

我处于一种奇怪的情况下,为了使我的包被正确调用,需要在调用脚本旁边以及在使用该文件的包文件夹中放置一个文件(models.py)。 为了更清楚一点,这是程序包组织的样子:

-FV_dir
 ---__init__.py
 ---F_V.py
 ---models.py
 ---utils.py
 ---service_utils.py
 ---subModule1_dir
    ----__init__.py
    ----detector.py
    ----utils.py
    ----subdir1
        --- etc
    ----subdir2
        --- etc
    ----subdir3

整个程序包都放在site-packages中,因此它在整个系统范围内都可用。并且有一个使用此程序包的用户脚本,如下所示:service_client.py

from FV.service_utils import ServiceCore
from FV.utils import a_helper_function

def run():
  service = ServiceCore()
  service.run()

if __name__ == "__main__":
   run()

ServiceCore本身使用F_V.py,这是这里的主要模块。F_V模块本身使用它旁边的models.pyutils.pyF_V.py

from FV.utils import func1, func2  
from FV.models import model1, model2, model3
...

现在的问题是,如果models.py不在客户端代码(service_client.py)旁边,它只会抱怨找不到模块:这是在这种情况下出现的示例错误:

           └─19146 /home/user1/anaconda3/bin/python3 /home/user1/Documents/service_client.py

Mar 17 19:22:54 ubuntu python3[19146]:     self.fv = FaceVerification(\*cfg['Face_Verification']['ARGS'])
Mar 17 19:22:54 ubuntu python3[19146]:   File "/home/user1/anaconda3/lib/python3.7/site-packages/FV/F_V.py", line 58, in __init__
Mar 17 19:22:54 ubuntu python3[19146]:     self._init_model()
Mar 17 19:22:54 ubuntu python3[19146]:   File "/home/user1/anaconda3/lib/python3.7/site-packages/FV/F_V.py", line 80, in _init_model
Mar 17 19:22:54 ubuntu python3[19146]:     checkpoint = torch.load(self.model_checkpoint_path, map_location=torch.device('cpu'))
Mar 17 19:22:54 ubuntu python3[19146]:   File "/home/user1/anaconda3/lib/python3.7/site-packages/torch/serialization.py", line 529, in 
Mar 17 19:22:54 ubuntu python3[19146]:     return _legacy_load(opened_file, map_location, pickle_module, \*pickle_load_args)
Mar 17 19:22:54 ubuntu python3[19146]:   File "/home/user1/anaconda3/lib/python3.7/site-packages/torch/serialization.py", line 702, in 
Mar 17 19:22:54 ubuntu python3[19146]:     result = unpickler.load()
Mar 17 19:22:54 ubuntu python3[19146]: ModuleNotFoundError: No module named 'models'

如果我删除F_V.py旁边的models.py,显然F_V.py会抱怨,因为它直接使用它:

          └─19216 /home/user1/anaconda3/bin/python3 /home/user1/Documents/fv_service_linux.py

Mar 17 19:27:33 ubuntu systemd[1532]: Started FV Service.
Mar 17 19:27:34 ubuntu python3[19216]: Traceback (most recent call last):
Mar 17 19:27:34 ubuntu python3[19216]:   File "/home/user1/Documents/fv_service_linux.py", line 83, in <module>
Mar 17 19:27:34 ubuntu python3[19216]:     from FV.service_utils import ServiceCore
Mar 17 19:27:34 ubuntu python3[19216]:   File "/home/user1/anaconda3/lib/python3.7/site-packages/FV/service_utils.py", line 21, in <mod
Mar 17 19:27:34 ubuntu python3[19216]:     from FV.F_V import FaceVerification
Mar 17 19:27:34 ubuntu python3[19216]:   File "/home/user1/anaconda3/lib/python3.7/site-packages/FV/F_V.py", line 17, in <module>
Mar 17 19:27:34 ubuntu python3[19216]:     from FV.models import resnet18, resnet50, resnet101
Mar 17 19:27:34 ubuntu python3[19216]: ModuleNotFoundError: No module named 'FV.models'

因此,使它起作用的唯一方法是在客户端代码旁边也要有“ models.py”。我不明白为什么会这样,因为客户端代码甚至没有直接与models.py交互。 我在这里想念什么?

更新:

F_V.py中,我使用Pytorch并加载一个预训练的模型。我认为这无关紧要,关于Python的包装我做错了,但是事实证明,这确实是罪魁祸首。阅读答案以获取更多信息。

问题来源:stackoverflow

Ubuntu Python
分享到
取消 提交回答
全部回答(1)
  • is大龙
    2020-03-21 11:53:24

    实际上恰好是一个与Pytorch相关的问题,其中整个问题是由在F_V.py中加载模型时通过此简单命令引起的:

    if self.device == 'cpu':
        checkpoint = torch.load(self.model_checkpoint_path, map_location=torch.device('cpu'))
    else:
        checkpoint = torch.load(self.model_checkpoint_path)
    # the culprit!
    self.model = checkpoint['model'].module
    

    这种存储和加载模型的方式非常糟糕,预先训练的模型最初是由nn.DataParallel和保存它们的人包装的,它是这样的:

    def save_checkpoint(epoch, epochs_since_improvement, model, metric_fc, optimizer, acc, is_best):
        print('saving checkpoint ...')
        state = {'epoch': epoch,
                 'epochs_since_improvement': epochs_since_improvement,
                 'acc': acc,
                 'model': model,
                 'metric_fc': metric_fc,
                 'optimizer': optimizer}
        # filename = 'checkpoint_' + str(epoch) + '_' + str(loss) + '.tar'
        filename = 'checkpoint.tar'
        torch.save(state, filename)
        # If this checkpoint is the best so far, store a copy so it doesn't get overwritten by a worse checkpoint
        if is_best:
            torch.save(state, 'BEST_checkpoint.tar')
    

    如您所见,他在state_dict中使用了整个模型('model':model)并将其保存下来。他应该使用过state_dict()。 这很不好,因为在要使用此模型的任何地方,必须始终保留相同的文件/目录结构层次结构/所有内容。 正如您所看到的,我们受到了这一影响。所有的客户端服务都依赖于models.py`,并且需要它们在它们甚至不使用的情况下与它们相邻。 因此,起初我认为为了解决该问题,我们必须自己实例化模型,然后手动加载权重。

    if self.model_name == 'r18':
        self.model = resnet18(pretrained=False, use_se=use_se)
    elif self.model_name == 'r50':
        self.model = resnet50(pretrained=False, use_se=use_se)
    elif self.model_name == 'r101':
        self.model = resnet101(pretrained=False, use_se=use_se)
    else:
        raise Exception(f"Model name: '{self.model_name}' is not recognized.")
    
    # load the model weights
    self.model.load_state_dict(checkpoint['model'].module.state_dict())
    

    注意,由于该模型最初是nn.DataParallel模型,因此为了访问模型本身,我们使用.module属性,然后使用state_dict()模型初始化模型,并希望这可以解决问题。 但是,似乎并非如此,并且由于以这种方式保存了模型,因此似乎没有办法以这种方式摆脱这种依赖性。而是将模型转换为割炬脚本,然后保存模型。 这样,您就可以摆脱所有的麻烦。

    解决方案1:

    尝试将模型转换为“火炬脚本”,然后改用它:

    def convert_model(model, input=torch.tensor(torch.rand(size=(1,3,112,112)))):
            model = torch.jit.trace(self.model, input)
            torch.jit.save(model,'/home/Rika/Documents/models/model.tjm')
    

    然后加载此版本:

    # load the model 
    self.model = torch.jit.load('/home/Rika/Documents/models/model.tjm')
    

    解决方案2:

    只需再次保存模型的state_dict()并使用它即可:我自己最终做了:

    self.model = checkpoint['model'].module
    # create the new checkpoint based on what you need 
    torch.save({'state_dict' : self.model.state_dict(), 'use_se':True},
                '/home/Rika/Documents/BEST_checkpoint_r18_2.tar')
    
    and started using the new checkpoint and so far everything has been good 
    

    回答来源:stackoverflow

    0 0
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

推荐文章
相似问题
推荐课程