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
