Загрузить модуль Python не из файла - PullRequest
3 голосов
/ 14 января 2011

У меня есть некоторый код Python в библиотеке, который пытается загрузить простое значение из модуля, который будет существовать для приложений, использующих эту библиотеку

from somemodule import simplevalue

Обычно приложение, использующее библиотеку, имеет файл модуля, и все работает нормально. Однако в модульных тестах для этой библиотеки модуль не существует. Я знаю, что могу создать временный файл и добавить этот файл к моему пути во время выполнения, но мне было любопытно, есть ли в python способ загрузить что-то в память, что позволило бы работать вышеупомянутым импортом.

Это больше любопытно, так как «добавить модуль в ваш тестовый путь» бесполезно: P

Ответы [ 3 ]

7 голосов
/ 14 января 2011

Это так.Используйте types.ModuleType для создания нового объекта модуля, затем добавьте его к sys.modules:

sys.modules["somename"] = types.ModuleType("somename")

Затем вы можете сделать import somename.Если вам нужно добавить к нему классы или функции, импортируйте их перед вызовом тестового скрипта и просто добавьте в него функции:

def myfunc(x, y, z):
    ...

somename.myfunc = myfunc

Это само собой разумеется, но на всякий случай: это в значительной степениакадемическое любопытство.У него есть несколько применений для тестирования, но помимо этого, он придерживается обычного способа импорта.

Кстати, как я об этом знаю: я наткнулся на методику, использованную в тестировании, чтобы сделать «заглушку»"для модуля _winreg в системах, отличных от Windows. Здесь используется .

5 голосов
/ 14 января 2011

Нет необходимости создавать модуль.Ни один код Python не заботится о том, действительно ли somemodule.simplevalue является ссылкой на атрибут модуля.Для этого программе необходимо проверить тип somemodule.Зачем беспокоиться?

Поскольку вы просто хотите получить одно значение из модуля и импортировать его в свое собственное пространство имен, просто определите его:

simplevalue = 42

Если хотите, используйте try/except дляпопробуйте сначала импортировать реальный модуль.

try:
    from somemodule import simplevalue
except ImportError:
    simplevalue = 42

Если вы импортируете весь модуль, но используете только одно значение, вы можете использовать класс для определения пространства имен.

try:
    import somemodule
except ImportError:
    class somemodule(object):
        simplevalue = 42

Теперьsomemodule.simplevalue относится к значению независимо от того, доступен ли модуль.

Если вы хотите, чтобы другие модули, которые также импортируют somemodule, увидели ваш поддельный класс как модуль, как в вашем устройстветест, просто сделай это потом:

import sys
sys.modules["somemodule"] = somemodule
1 голос
/ 14 января 2011

Ваша тестируемая система (sut в моем примере) должна быть в состоянии справиться с тем фактом, что somemodule может не существовать, поэтому вы можете перехватить ImportError:

#!/usr/bin/env python

try:
    from somemodule import simplevalue
except ImportError, e:
    if 'somemodule' in e:
        '''We expect that to happen in the unittest but you should log something for when
         this happens in production'''

def fn():
    return simplevalue

Затем вы можете ввести значение в свой юнит-тест:

#!/usr/bin/env python

import unittest
import sut

class T(unittest.TestCase):

    def test_fn(self):
        sut.simplevalue = 42
        self.assertEquals(42, sut.fn())


if __name__ == '__main__':
    unittest.main()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...