2011-02-25 3 views
12

파이썬에서 패키지를 위조하고 싶습니다. 나는 코드가테스트 용으로 파이썬에서 패키지 (또는 적어도 모듈)를 "가짜"로 만들 수 있습니까?

from somefakepackage.morefakestuff import somethingfake 

을 할 수있는 그리고 somefakepackage이 코드에서 정의 될 수 있도록 뭔가를 정의 할 그래서 그 아래 모든입니다. 그게 가능하니? 이 일을하는 이유는 실제로 내가 unittest를 위해 조롱 한 python 경로의 패키지 (또는 제목에서 말했듯이, 모듈)를 가지고있는 나의 unittest를 속이는 것입니다.

감사합니다.

+2

찾고 계신 단어는 ___ 모크 ___입니다. 이 질문은 도움이 될 수도 있습니다. http://stackoverflow.com/questions/295438 –

답변

19

확실히. 클래스를 정의하고, 안에 필요한 것들을 넣고, 클래스를 sys.modules["classname"]에 할당하십시오.

class fakemodule(object): 

    @staticmethod 
    def method(a, b): 
     return a+b 

import sys 
sys.modules["package.module"] = fakemodule 

또한 별도의 모듈 (fakemodule.py를 호출) 사용할 수 있습니다

import fakemodule, sys 

sys.modules["package.module"] = fakemodule 
+5

이 트릭 중 하나는 최상위 속성으로'__path__ = []'을 사용하여'package'를위한 가짜 모듈을 삽입하는 것입니다. 이것이 없으면 모듈 계층이 불완전하여 일부 도구를 혼동시킬 수 있습니다. – ncoghlan

+0

좋은, 좋은 추가. – kindall

+0

그냥 추가하십시오. 예를 들어 하위 모듈을 가져 오는 경우 'import a.b.c'를 사용하려면, 위조 모듈을 'sys.modules [ "a"]','sys.modules [ "a.b"]'그리고'sys.modules [ "a.b.c"]' –

2

을 당신 수 somethingfake처럼 동작하는 클래스와 가짜 :

try: 
    from somefakepackage.morefakestuff import somethingfake 
except ImportError: 
    class somethingfake(object): 
     # define what you'd expect of somethingfake, e.g.: 
     @staticmethod 
     def somefunc(): 
      ... 
     somefield = ... 
4

예, 당신이 할 수있는 가짜 모듈 만들기 :

from types import ModuleType 
m = ModuleType("fake_module") 

import sys 
sys.modules[m.__name__] = m 

# some scripts may expect a file 
# even though this file doesn't exist, 
# it may be used by Python for in error messages or introspection. 
m.__file__ = m.__name__ + ".py" 

# Add a function 
def my_function(): 
    return 10 

m.my_function = my_function 

이 예제에서는 실제 모듈 (ModuleType)을 사용하고 있습니다. 이는 파이썬 코드가 더미 클래스 대신 모듈을 필요로하기 때문입니다.

는 유틸리티 함수로 만들 수 있습니다에게 :
def new_module(name, doc=None): 
    import sys 
    from types import ModuleType 
    m = ModuleType(name, doc) 
    m.__file__ = name + '.py' 
    sys.modules[name] = m 
    return m 

print(new_module("fake_module", doc="doc string")) 

지금 다른 스크립트를 실행할 수 있습니다

import fake_module 
1

내가 다른 답변에서 몇 가지 아이디어를 가져다 파이썬 데코레이터로 설정되어 @modulize 함수를 모듈로 변환합니다. 이 모듈은 평소대로 가져올 수 있습니다. 다음은 그 예입니다.

import sys 
from types import ModuleType 

class MockModule(ModuleType): 
    def __init__(self, module_name, module_doc=None): 
     ModuleType.__init__(self, module_name, module_doc) 
     if '.' in module_name: 
      package, module = module_name.rsplit('.', 1) 
      get_mock_module(package).__path__ = [] 
      setattr(get_mock_module(package), module, self) 

    def _initialize_(self, module_code): 
     self.__dict__.update(module_code(self.__name__)) 
     self.__doc__ = module_code.__doc__ 

def get_mock_module(module_name): 
    if module_name not in sys.modules: 
     sys.modules[module_name] = MockModule(module_name) 
    return sys.modules[module_name] 

def modulize(module_name, dependencies=[]): 
    for d in dependencies: get_mock_module(d) 
    return get_mock_module(module_name)._initialize_ 

프로젝트

here on GitHub를 찾을 수 있습니다 다음과 같이

@modulize('my_module') 
def my_dummy_function(__name__): # the function takes one parameter __name__ 
    # put module code here 
    def my_function(s): 
     print(s, 'bar') 

    # the function must return locals() 
    return locals() 

# import the module as usual 
from my_module import my_function 
my_function('foo') # foo bar 

데코레이터에 대한 코드입니다. 특히, 참가자가 하나의 .py 파일 만 제출하도록 허용하는 프로그래밍 콘테스트 용으로 제작했습니다. 이를 통해 여러 .py 파일로 프로젝트를 개발 한 다음 끝에 하나의 .py 파일로 결합 할 수 있습니다.

관련 문제