Переопределение `из импорта my_module ...` - PullRequest
0 голосов
/ 28 июня 2018

Я пытаюсь заставить работать следующее:

from my_module import some_random_string

и мой модуль должен перехватить это и вернуть определенные значения на основе some_random_string.

Я попытался настроить хук импорта, но он не работает должным образом:

# custom_import.py
import sys

class MyImporter(object):
    def find_module(self, filename, path):
        print(filename, path)
        return "foobar"

    def load_module(self, module_name):
        print(module_name)
        return "foobar"

sys.meta_path.append(MyImporter())
# interactive console
>>> from custom_import import some_string
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name some_string
>>>

Почему это так и как это исправить?

1 Ответ

0 голосов
/ 29 июня 2018

Чтобы иметь возможность импортировать любой объект, которого нет в my_module (при условии, что my_module существует и доступен), мы можем начать с простого переноса my_module, как

import importlib
import sys
import types


class ModuleWrapper:
    def __init__(self, module):
        self.module = module

    @property
    def __path__(self):
        return None

    def __getattr__(self, name):
        try:
            return getattr(self.module, name)
        except AttributeError:
            # returning `module` object is not necessary, 
            # can be something else
            return types.ModuleType(name)


my_module = importlib.import_module('my_module')
sys.modules['my_module'] = ModuleWrapper(my_module)

Тест

Со структурой проекта

my_module.py

test.py

и содержимое

  • my_module.py

    ...snippet above...
    some_name = 'Sample text'
    
  • test.py

    from my_module import some_name, z
    
    print(some_name)
    print(z)
    

выполнение

> python test.py

дает нам в Python2.7.0

Sample text
<module 'z' (built-in)>

и Python3.5.4

Sample text
<module 'z'>
...