2017-03-29 9 views
1

기본적으로 특정 모듈의 모든 기능을로드하고 (존재하는 경우) 클래스 메소드와 병합하려고합니다. 내가 __new__ 내부에 빌드되고있는 클래스의 __module__을 가지고 있다면 모듈에 직접 경로를 만들고 가져올 수 있습니다. 내 문제를 해결하기 위해 get_module_fns을 찾고 있습니다. 나는 다음과 같은 것을하고 싶다 :metaclass의 __new__에서 모듈을 발견 할 때의 문제

get_module_fns('pathto.mod1.toimport') 

만약 존재한다면, 모든 기능을 dict로 반환 할 것이다.

코드 및 테스트에 대해서는 link입니다.

# mtcl.py 
import inspect 
import imp 


def get_module_fns(module_name, module_path): 
    try: 
     mod_loaded = imp.load_source(module_name, module_path) 
     module_fns = [(name, func) for name, func in 
         inspect.getmembers(mod_loaded, inspect.isfunction)] 
    except FileNotFoundError as e: 
     return {} 
    except ImportError as e: 
     return {} 
    return dict(module_fns) 


class GetModuleFunctions(type): 

    def __new__(cls, name, bases, namespaces, **kwargs): 

     module_functions = get_module_fns('toimport', './toimport.py') 
     namespaces.update(module_functions) 

     new_class = super(GetModuleFunctions, cls).__new__(
      cls, name, bases, namespaces) 

     new_class._mdl_fns = module_functions 

     return new_class 


class ClassBase(metaclass=GetModuleFunctions): 

    def __init__(self, *args, **kwargs): 
     super(ClassBase, self).__init__(*args, **kwargs) 

    @property 
    def module_functions(self): 
     return self.__class__._mdl_fns 
# mod0.py 
from .mtcl import ClassBase 


class M0(ClassBase): 

    def function_m0(self): 
     return 0 
# mod1/__init__.py 
from ..mtcl import ClassBase 


class M1(ClassBase): 

    def function_m1(self): 
     return 1 
# mod1/toimport.py 

def function_1(obj, *args, **kwargs): 
    return 1 
# mod1/mod2/__init__.py 
from ...mtcl import ClassBase 


class M2(ClassBase): 

    def function_m2(self): 
     return 2 
# mod1/mod2/toimport.py 

def function_2(obj, *args, **kwargs): 
    return 2 

답변

1

TR Y 다음

import inspect 
import importlib 


def get_module_fns(cls, module_name): 
    try: 
     mod_loaded = importlib.import_module(
      '%s.%s' % (cls.__module__, module_name) 
     ) 
     module_fns = [(name, func) for name, func in 
         inspect.getmembers(mod_loaded, inspect.isfunction)] 
    except ModuleNotFoundError as e: 
     return {} 
    except ImportError as e: 
     return {} 
    return dict(module_fns) 


class GetModuleFunctions(type): 

    def __new__(cls, *args, **kwargs): 
     new_class = super(GetModuleFunctions, cls).__new__(
      cls, *args, **kwargs) 
     module_functions = get_module_fns(new_class, 'toimport') 
     for name, fn in module_functions.items(): 
      setattr(new_class, name, fn) 
     new_class._mdl_fns = module_functions 
     return new_class 

당신이 당신의 클래스의 모듈 내에서 모듈을 찾고 있기 때문에,이 그것을 수행해야합니다

mod_loaded = importlib.import_module(
    '%s.%s' % (cls.__module__, module_name) 
) 

을 슬프게도, 당신은 사용할 수 없습니다 namespace__new__.super 후 :

for name, fn in module_functions.items():     
    setattr(new_class, name, fn)