On Tue, Oct 16, 2012 at 08:23:39AM +0900, FUJITA Tomonori wrote:
> On Sun, 14 Oct 2012 12:14:11 +0900
> Isaku Yamahata <[email protected]> wrote:
> 
> > On Sat, Oct 13, 2012 at 02:44:32AM +0900, FUJITA Tomonori wrote:
> >> On Fri, 12 Oct 2012 17:28:50 +0900
> >> Isaku Yamahata <[email protected]> wrote:
> >> 
> >> > On Fri, Oct 12, 2012 at 07:39:21AM +0900, FUJITA Tomonori wrote:
> >> >> On Thu, 11 Oct 2012 17:17:15 +0900
> >> >> Isaku Yamahata <[email protected]> wrote:
> >> >> 
> >> >> > Since import_module() isn't aware of cwd, so it may result in double 
> >> >> > import.
> >> >> > Avoid double import.
> >> >> 
> >> >> Elaborate how it happens, please.
> >> > 
> >> > I'll add the following to the commit message.
> >> > 
> >> > In the following example, the first one(ryu.app.event_dumper) imports the
> >> > module, ryu.app.event_dumper, relative to ryu/.., the second one
> >> > (ryu/app/event_dumper.py) imports the module, event_dumper, relative to
> >> > ryu/app. Python thinks that they are different modules.
> >> > Although it doesn't make much sense to instantiate same application 
> >> > twice,
> >> > I don't think of any reason to prevent it. And it is difficult to 
> >> > understand
> >> > what's happening.
> >> 
> >> I can see what problem you try to solve but I'm not sure you did. Even
> >> with this patch, I hit the same problem with:
> >> 
> >> $ pwd
> >> /home/fujita/git/ryu/ryu/app
> >> $ ryu-manager --app_lists=ryu.app.event_dumper --app_lists=event_dumper.py
> >> 
> >> 
> >> If we can fix the problem completely, I can see the benefit. But this
> >> patch fixes the problem partially.
> > 
> > How about this approach? pseudo code
> > The issue is, given application can be loaded both from (unmodified) 
> > sys.path
> > and from its parent directly when it endswith('.py')
> > So how about trying to load module when relative path is given?
> 
> You can put the file name that doesn't end with '.py' in command
> line. So I'm not sure how your idea works.

The following path checks if the given path can be loaded from module
load path by checking __init__.py.

>From a729fe9b33a3a754dec62982b1286680796a8205 Mon Sep 17 00:00:00 2001
Message-Id: 
<a729fe9b33a3a754dec62982b1286680796a8205.1351197942.git.yamah...@valinux.co.jp>
In-Reply-To: <[email protected]>
References: <[email protected]>
From: Isaku Yamahata <[email protected]>
Date: Tue, 18 Sep 2012 18:21:57 +0900
Subject: [PATCH 04/43] utils: avoid double import and don't append sys.path
 with same path

sys.path can be populated with same path. Don't append when path is already
added.
ryu-manager --app_lists=ryu/app/rest.py --app_lists=ryu/app/simple_isolation.py
This results that sys.path[-2:] has two same value.
This isn't critical, but annoying when debuging module loading stuff.

Since import_module() isn't aware of cwd, so it may result in double import.
Avoid double import.
In the following example, the first one(ryu.app.event_dumper) imports the
module, ryu.app.event_dumper, relative to ryu/.., the second one
(ryu/app/event_dumper.py) imports the module, event_dumper, relative to
ryu/app. Python thinks that they are different modules.
Although it doesn't make much sense to instantiate same application twice,
I don't think of any reason to prevent it. And it is difficult to understand
what's happening.

> $ PYTHONPATH=$(pwd) ./bin/ryu-manager ryu.app.event_dumper 
> ryu/app/event_dumper.py
> loading app ryu.controller.ofp_handler
> loading app ryu.app.event_dumper
> loading app ./ryu/app/event_dumper.py
> Traceback (most recent call last):
>   File "./bin/ryu-manager", line 81, in <module>
>     main()
>   File "./bin/ryu-manager", line 61, in main
>     app_mgr.load_apps(FLAGS.app_lists)
>   File "/ryu/base/app_manager.py", line 94, in load_apps
>     cls = self.load_app(app_cls_name)
>   File "/ryu/base/app_manager.py", line 74, in load_app
>     mod = utils.import_module(name)
>   File "/ryu/utils.py", line 34, in import_module
>     __import__(name)
>   File "ryu/app/event_dumper.py", line 29, in <module>
>     'list of dispatcher name to dump event: default any')
>   File "/usr/lib/python2.7/dist-packages/gflags.py", line 2673, in 
> DEFINE_multistring
>     DEFINE_multi(parser, serializer, name, default, help, flag_values, **args)
>   File "/usr/lib/python2.7/dist-packages/gflags.py", line 2660, in 
> DEFINE_multi
>     flag_values)
>   File "/usr/lib/python2.7/dist-packages/gflags.py", line 2045, in DEFINE_flag
>     fv[flag.name] = flag
>   File "/usr/lib/python2.7/dist-packages/gflags.py", line 916, in __setitem__
>     raise DuplicateFlagError(name, self)
> gflags.DuplicateFlagError: The flag 'dump_queue' is defined twice. First from 
> ryu.app.event_dumper, Second from event_dumper

Signed-off-by: Isaku Yamahata <[email protected]>
---
 ryu/utils.py |   63 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 54 insertions(+), 9 deletions(-)

diff --git a/ryu/utils.py b/ryu/utils.py
index f2da670..9b0146b 100644
--- a/ryu/utils.py
+++ b/ryu/utils.py
@@ -18,22 +18,67 @@
 import inspect
 import logging
 import os
+import os.path
 import sys
 
 LOG = logging.getLogger('ryu.utils')
 
 
+def _abspath(path):
+    if path == '':
+        path = '.'
+    return os.path.abspath(path)
+
+
+def _split_modname(modpath):
+    sys_path = [_abspath(path) for path in sys.path]
+    modname = os.path.basename(modpath)
+    dirname = os.path.dirname(modpath)
+    while True:
+        if dirname in sys_path:
+            break
+        if not os.path.exists(os.path.join(dirname, '__init__.py')):
+            break
+
+        basename = os.path.basename(dirname)
+        if basename:
+            old_dirname = dirname
+            dirname = os.path.dirname(dirname)
+            if old_dirname == dirname:
+                break
+            if modname:
+                modname = basename + '.' + modname
+            else:
+                modname = basename
+        else:
+            break
+
+    return dirname, modname
+
+
+def _import(modname):
+    __import__(modname)
+    return sys.modules[modname]
+
+
 def import_module(modname):
     try:
-        __import__(modname)
-    except:
-        sys.path.append(os.path.dirname(os.path.abspath(modname)))
-        name = os.path.basename(modname)
-        if name.endswith('.py'):
-            name = name[:-3]
-        __import__(name)
-        return sys.modules[name]
-    return sys.modules[modname]
+        return _import(modname)
+    except ImportError:
+        pass
+
+    if modname.endswith('.py'):
+        modname = modname[:-3]
+        try:
+            return _import(modname)
+        except ImportError:
+            pass
+
+    modname = os.path.abspath(modname)
+    dirname, name = _split_modname(modname)
+    if dirname not in [_abspath(path) for path in sys.path]:
+        sys.path.append(dirname)
+    return _import(name)
 
 
 RYU_DEFAULT_FLAG_FILE = ('ryu.conf', 'etc/ryu/ryu.conf' '/etc/ryu/ryu.conf')
-- 
1.7.10.4



-- 
yamahata

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_sfd2d_oct
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to