Search code examples
pythonpython-2.7importisinstancedynamic-import

python 2.7 isinstance fails at dynamically imported module class


I'm currently writing some kind of tiny api to support extending module classes. Users should be able to just write their class name in a config and it gets used in our program. The contract is, that the class' module has a function called create(**kwargs) to return an instance of our base module class, and is placed in a special folder. But the isinstance check Fails as soon as the import is made dynamically.

modules are placed in lib/services/name

module base class (in lib/services/service)

class Service:
    def __init__(self, **kwargs):
        #some initialization

example module class (in lib/services/ping)

class PingService(Service):
    def __init__(self, **kwargs):
        Service.__init__(self,**kwargs)
        # uninteresting init

def create(kwargs):
    return PingService(**kwargs)

importing function

import sys
from lib.services.service import Service

def doimport( clazz, modPart, kw, class_check):
    path = "lib/" + modPart
    sys.path.append(path)
    mod = __import__(clazz)
    item = mod.create(kw)

    if class_check(item):
        print "im happy"
        return item

calling code

class_check = lambda service: isinstance(service, Service)
s = doimport("ping", "services", {},class_check)

print s

from lib.services.ping import create

pingService = create({})
if isinstance(pingService, Service):
    print "why this?"

what the hell am I doing wrong

here is a small example zipped up, just extract and run test.py without arguments zip example


Solution

  • The problem was in your ping.py file. I don't know exactly why, but when dinamically importing it was not accepting the line from service import Service, so you just have to change it to the relative path: from lib.services.service import Service. Adding lib/services to the sys.path could not make it work the inheritance, which I found strange...

    Also, I am using imp.load_source which seems more robust:

    import os, imp
    def doimport( clazz, modPart, kw, class_check):
        path = os.path.join('lib', modPart, clazz + '.py')
        mod = imp.load_source( clazz, path )
        item = mod.create(kw)
    
        if class_check(item):
            print "im happy"
            return item