загрузка модулей с помощью imp.load_source с тем же именем, что приводит к слиянию модулей

Я хотел бы знать, ожидается ли следующее поведение или ошибка. Я использую CPython2.7

Создать файл x.py

def funcA(): print "funcA of x.py" def funcB(): print "funcB of x.py" 

Создать файл y.py

 def funcB(): print "funcB of y.py" 

Создать файл test.py

 import sys, imp # load x.py as fff m = imp.load_source('fff', 'x.py') print dir(m) print sys.modules.get('fff') # load y.py as fff m = imp.load_source('fff', 'y.py') print dir(m) print sys.modules.get('fff') # import and exec func import fff fff.funcA() fff.funcB() print dir(fff) 

Результат

 ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'funcA', 'funcB'] <module 'fff' from 'x.py'> ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'funcA', 'funcB'] <module 'fff' from 'y.py'> funcA of x.py funcB of y.py ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'funcA', 'funcB'] 

Мое предположение состояло в том, что 2-й источник imp.load_source полностью заменит модуль x.py на y.py. Фактически sys.modules.get('fff') показывает <module 'fff' from 'y.py'> но полученный модуль был похож на сочетание x.py и y.py, а последнее имеет приоритет.

Ожидается ли это или ошибка?

EDIT: у моего тестового кода была опечатка. обновил результат.

  • Классы и методы, со списками в Python
  • time.sleep - TypeError: требуется поплавок
  • Простой пример счетчика с использованием mapreduce в Google App Engine
  • Вывести скрипт python в текстовый файл
  • Получение индекса возвращаемого значения max или min с помощью max () / min () в списке
  • При проверке, нет ли элемента в списке, почему этот код не работает - если элемент в списке == False:
  • Python strip () несколько символов?
  • Почему вы не должны использовать os.linesep при редактировании в текстовом режиме?
  • One Solution collect form web for “загрузка модулей с помощью imp.load_source с тем же именем, что приводит к слиянию модулей”

    Это ожидаемое поведение.
    См. http://docs.python.org/2/library/imp.html.

    imp.load_source (имя, путь [, файл])

    Загрузите и инициализируйте модуль, реализованный как исходный файл Python, и верните его объект модуля. Если модуль уже был инициализирован, он будет снова инициализирован. Аргумент name используется для создания или доступа к объекту модуля.

    Поскольку ваш второй модуль имеет то же имя, что и первый модуль, он не заменит первый, но будет объединен с первым.

    Исходный код дает нам тот же ответ.
    imp – это встроенный модуль, определенный в import.c .
    Давайте посмотрим на определение load_source

     static PyObject * load_source_module(char *name, char *pathname, FILE *fp) { ...... m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname); Py_DECREF(co); return m; } 

    Это всего лишь оболочка для PyImport_ExecCodeModuleEx .

     PyObject * PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) { PyObject *modules = PyImport_GetModuleDict(); PyObject *m, *d, *v; m = PyImport_AddModule(name); ...... d = PyModule_GetDict(m); ...... v = PyEval_EvalCode((PyCodeObject *)co, d, d); ...... } 

    Теперь нам просто нужно сосредоточиться на PyImport_AddModule . Python использует его для получения объекта модуля. Исправленный исходный файл будет помещен в этот объект модуля.

     PyObject * PyImport_AddModule(const char *name) { PyObject *modules = PyImport_GetModuleDict(); PyObject *m; if ((m = PyDict_GetItemString(modules, name)) != NULL && PyModule_Check(m)) return m; m = PyModule_New(name); if (m == NULL) return NULL; if (PyDict_SetItemString(modules, name, m) != 0) { Py_DECREF(m); return NULL; } Py_DECREF(m); /* Yes, it still exists, in modules! */ return m; } 

    Наконец, мы находим ответ. Учитывая name , если какой-то модуль уже имеет это name , а именно name in sys.modules , Python не будет создавать новый модуль, но будет повторно использовать этот модуль.

    Python - лучший язык программирования в мире.