Ryu的app导入model失败问题解决

这几天在写ryu的app是需要导入其他的文件夹下的程序,像这样:

from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.ofproto.StartModel import StartIdentify
from Cnn_Identify_Model.RyuNetwork.test import test

在pycharm下的terminal输入:
ryu-manager Cnn_Identify_Model/RyuNetwork/StartNetwork.py是发现模块导入失败:

Traceback (most recent call last):
  File "/root/PycharmProjects/HuaWeiBei/venv/bin/ryu-manager", line 11, in <module>
    load_entry_point('ryu==4.32', 'console_scripts', 'ryu-manager')()
  File "/root/PycharmProjects/HuaWeiBei/venv/lib/python3.5/site-packages/ryu/cmd/manager.py", line 100, in main
    app_mgr.load_apps(app_lists)
  File "/root/PycharmProjects/HuaWeiBei/venv/lib/python3.5/site-packages/ryu/base/app_manager.py", line 416, in load_apps
    cls = self.load_app(app_cls_name)
  File "/root/PycharmProjects/HuaWeiBei/venv/lib/python3.5/site-packages/ryu/base/app_manager.py", line 392, in load_app
    mod = utils.import_module(name)
  File "/root/PycharmProjects/HuaWeiBei/venv/lib/python3.5/site-packages/ryu/utils.py", line 104, in import_module
    return _import_module_file(modname)
  File "/root/PycharmProjects/HuaWeiBei/venv/lib/python3.5/site-packages/ryu/utils.py", line 92, in _import_module_file
    return load_source(modname, abspath)
  File "/root/PycharmProjects/HuaWeiBei/venv/lib/python3.5/site-packages/ryu/utils.py", line 44, in load_source
    return loader.load_module(name)
  File "<frozen importlib._bootstrap_external>", line 388, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 809, in load_module
  File "<frozen importlib._bootstrap_external>", line 668, in load_module
  File "<frozen importlib._bootstrap>", line 268, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 693, in _load
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "/root/PycharmProjects/HuaWeiBei/Cnn_Identify_Model/RyuNetwork/StartNetwork.py", line 11, in <module>
    from Cnn_Identify_Model.RyuNetwork.test import test
ImportError: No module named 'Cnn_Identify_Model'

难受,只能去解决。按照他提示的错误一步一步的去跟踪并输出一些中间结果。

app_lists:['Cnn_Identify_Model/RyuNetwork/StartNetwork.py']
app_mgr.load_apps(app_lists)
app_cls_name:Cnn_Identify_Model/RyuNetwork/StartNetwork.py
cls = self.load_app(app_cls_name)
mod = utils.import_module(name)
modname:Cnn_Identify_Model/RyuNetwork/StartNetwork.py
return _import_module_file(modname)
#下面要多输出一些
def _import_module_file(path):
    abspath = os.path.abspath(path)

    # Backup original sys.path before appending path to file
    original_path = list(sys.path)
    sys.path.append(os.path.dirname(abspath))
    modname = chop_py_suffix(os.path.basename(abspath))
    print(list(sys.path))
    sys.path
['/root/PycharmProjects/HuaWeiBei/venv/bin', '/usr/lib/python35.zip', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-x86_64-linux-gnu', '/usr/lib/python3.5/lib-dynload', '/root/PycharmProjects/HuaWeiBei/venv/lib/python3.5/site-packages', '/root/PycharmProjects/HuaWeiBei/venv/lib/python3.5/site-packages/setuptools-40.8.0-py3.5.egg', '/root/PycharmProjects/HuaWeiBei/venv/lib/python3.5/site-packages/pip-19.0.3-py3.5.egg', '/root/PycharmProjects/HuaWeiBei/Cnn_Identify_Model/RyuNetwork']

    try:
        return load_source(modname, abspath)
    finally:
        # Restore original sys.path
        sys.path = original_path

是什么原因导致了这个问题,他说那个模块不存在,那么python是如何检查一个model是否存在的?于是在网上搜了一下找到了结果,他说需要在sys.path里要有相关的路径。就是之前在中间过程里打印出来的sys.path。但是可以看到
/root/PycharmProjects/HuaWeiBei/Cnn_Identify_Model/RyuNetwork已经再里面了。后来发现不是这样的,我只是把RyuNetwork导入进来了。并没有将Cnn_Identify_Model放置到sys.path当中。于是这个就需要手动的来添加。

可以使用sys.path.append()来添加相应的model路径。

当然还有两个不需要添加这个路径的方法。
第一个就是将需要导入的文件放入到sys.path的检查路径中。之前我就是通过此方法,将文件放置到ryu的ofproto的文件夹下来解决问题的。
第二个就是只是用一个文件夹,比如我的是RyuNetwork,那么所有的程序都放到这个文件夹下,那么就不会有问题。原因是上面的_import_module_file(utils)里向sys.path添加了这个文件夹的路径。

所以总而言之三种方法:
1.使用sys.path.append(),比如sys.path.append(“root/PycharmProjects/HuaWeiBei/”)这样就不用考虑导入问题了,这个项目文件夹都在path路径中了。
2.只是用一个文件夹。ryu会在load_model是向sys.path添加上此文件所在目录的。
3.将需要导入的文件放置到sys.path中。(可以使用print(sys.path)来查看sys.path与那些路径)

可是使用sys.path有一个问题就是ryu-manage是先导入模块,再去执行相应的代码,如果在代码中执行sys.path那就迟了。于是我给出一种解决思路就是在utils中添加函数来解决问题。添加的函数中传入的是ryu程序的绝对路径,通过解析绝对路径来阻隔向sys.path来添加路径,这样就解决了sys.path不能执行的问题,也解决了不知道项目名字和具体的文件夹的问题。

def addtosyspath(path):
    kk = path.split('/')[1:-1]
    str = '/'
    for i in range(len(kk)):
        str += kk[i] + '/'
        #逐个添加路径
        sys.path.append(str)

def _import_module_file(path):
    abspath = os.path.abspath(path)
    # Backup original sys.path before appending path to file
    original_path = list(sys.path)
    addtosyspath(abspath)
    sys.path.append(os.path.dirname(abspath))
    sys.path.append(rootdir)
    print(sys.path)

    modname = chop_py_suffix(os.path.basename(abspath))

    try:
        return load_source(modname, abspath)
    finally:
        # Restore original sys.path
        sys.path = original_path

但是黑有一个问题就是如果导入的文件在同文件夹下的子文件夹,这时便遍历不到相应的文件夹了。如果使用每个文件并判断其是否是文件夹,那么就不值得了,原因是文件夹将会非常长的多,一次性检查这么多的文件夹会耗时,而且后面执行文件需要依据此sys.path来查找具体的导入文件也是一个耗时过程。
后来发现在manager.py的代码中有这么一段:
app_lists = CONF.app_lists + CONF.app
经检测CONF.app_lists有用,所以打印出来看一下:
[‘Cnn_Identify_Model/RyuNetwork/StartNetwork.py’],这下终于知道了ryu拿到的其实是相对路径,那么就可以根据绝对路径找到ryu的app所在的项目的项目名了。再依据项目名来遍历其下的文件夹,如果是文件夹,在判断其是否在sys.path中,若在就不添加了。这个时候还是要改下ryu的代码的,方便其传输CONF.app。
需要改的地方为:

manage的app_mgr.load_apps(app_lists),添加一个参数,为了方便与之前的系统兼容参数默认为None
像这样:
app_mgr.load_apps(app_lists,app_list)
def load_app(self, name,relativepath=None):
       #在这里添加得到项目路径方法
       #获取文件的绝对路径
        abspath = sys.path.abspath(name)
        #由于relativepath是一个列表且只有一个值所以需要将其取出来再传值
        self.addpath(abspath,relativepath[0])
        mod = utils.import_module(name)
def addpath(self,abspath,relativepath):
       #分割路径,取出中间的必要信息
	   absp = abspath.split('/')[1:-1]
	   relativep = relativepath.split('/')[:-1]
	   path = '/'
	   for i in range(len(absp)):
	        #这样做的原因是相对路径的绝对路径的一个子路径
	        #只需要取到相对路径前面的那一段路径就可以了,那个就是项目的路径
	   		if absp[i] == relativep[0]:
	   			break
	   		path+=absp[i]+"/"
	   	#将其添加到系统的路径列表中。
	   	sys.path.append(path)

经检测import导入是看最外面的包是否在sys.path的路径中所以只要找出项目文件名就可以解决问题了。相关代码很简单这里就略过了。
至此关于ryu的关于import导入失败问题解决。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值