Build a Python module on the fly, dynamic import

I'm trying to get to know the hooks importlib. I want to realize the ability to directly import non-pythonic files written in another language and support the source maps, so raising SyntaxErrorwith line numbers will still produce meaningful stacks.

My approach to downloading other people's files is to build the Pythonic source, then compile it and execute it in the right context.

I read in the documentation that the implementation importlib.abc.SourceLoaderseems to be my choice, but the only method that is called is this exec_module. At this point, in my opinion, the module object is completely ready. So why get_source, get_data, get_codeand others are not called?

My stub implementation:

import sys
import os

import importlib.abc
import importlib.machinery

class MyFinder(importlib.abc.MetaPathFinder):
    def __init__(self):
        pass

    def find_spec(self, fullname, path, target=None):
        print('find_spec', fullname, path, target)

        # filename = '{}.npy'.format(fullname)
        # if not os.path.exists(filename):
        #     return

        if fullname != 'foobar':
            return

        filename = 'foobar://ponyworld/foo.py'

        spec = importlib.machinery.ModuleSpec(
            name = fullname,
            loader = MyLoader(fullname, path, target),
            origin = filename,
            loader_state = 1234,
            is_package = False,
        )

        return spec

class MyLoader(importlib.abc.SourceLoader):
    def __init__(self, fullname, path, target):
        pass

    def get_data(self, path):
        print('get_data', path)

    def get_filename(self, fullname):
        print('get_filename', fullname)

    def path_stats(self, path):
        print('path_stats', path)

    def set_data(self, path, data):
        print('set_data', path, data)

    def get_code(self, fullname):
        print('get_code', fullname)

    def exec_module(self, module):
        print('exec_module', module)
        print(dir(module))

    def get_source(self, fullname):
        print('get_source', fullname)

    def is_package(self, fullname):
        print('is_package', fullname)

sys.meta_path.append(MyFinder())

# import fake module to see if it works
import foobar
+4
1

, importlib.abc.SourceLoader get_code, exec_module, load_module, get_source is_package. , get_data get_filename .

+2

All Articles