Search code examples
python

Are there any builtin frozen modules in python


I was going through the python import process and found out about frozen modules. The only thing I understood after searching is that frozen modules are files that can be directly executed without python installed on the system.

I wanted to know one thing. Like sys.modules and sys.builtin_module_names are any frozen modules also present in python that are loaded automatically when running python? If yes, can we also access a list of them somehow? My main goal is to know any names that I should avoid giving to the files.


Solution

  • If your goal is to know what names to avoid, you don't need to know about frozen modules for that. Just don't pick the name of a built-in function, stdlib module, or keyword, and you should be fine. So pretty much the 3 lists matszwecja linked.


    But learning about frozen modules is interesting too, so let's talk about those.

    Frozen modules aren't files that can be executed without Python installed. "Freezing" a Python program generates a custom executable containing a Python interpreter and embedded bytecode for all the Python files the program needs. Frozen modules are modules loaded from that embedded bytecode.

    Now, that description makes it sound like frozen modules would only exist as part of such special executables, but a standard Python interpreter actually does come with some frozen modules. Some of them are frozen because they're part of the import system itself, and freezing them makes it easier to set them up while the import system isn't ready yet. Some of them are frozen to serve as test cases for importing frozen modules. On more recent Python versions, a bunch of extra stdlib modules are also frozen because they're imported at Python startup, and freezing them makes startup faster.


    I don't think there's a Python-level interface to query the list of frozen modules. Your best bet would probably be to read the contents of Python/frozen.c for your Python version.

    If you want, you could access the C API, but they changed things in Python 3.11 when they added the extra frozen stdlib modules. On 3.10 and down, the frozen stdlib modules were all in the documented PyImport_FrozenModules array, so you could read that:

    import ctypes
    import itertools
    
    # Make sure this matches the definition in the docs:
    # https://docs.python.org/3/c-api/import.html#c._frozen
    class _frozen(ctypes.Structure):
        _fields_ = [('name', ctypes.c_char_p),
                    ('code', ctypes.POINTER(ctypes.c_ubyte)),
                    ('size', ctypes.c_int),
                    ('is_package', ctypes.c_bool)]
    
    PyImport_FrozenModules = ctypes.POINTER(_frozen).in_dll(ctypes.pythonapi, 'PyImport_FrozenModules')
    
    if PyImport_FrozenModules:
        for i in itertools.count():
            record = PyImport_FrozenModules[i]
            if record.name is None:
                break
            print(record.name)
    

    but since 3.11, PyImport_FrozenModules defaults to NULL, and the frozen stdlib modules have been moved into 3 undocumented arrays.

    If you want to access undocumented APIs, you can do it anyway:

    # Extra for Python 3.11 and up
    for name in ['_PyImport_FrozenBootstrap', '_PyImport_FrozenStdlib', '_PyImport_FrozenTest']:
        records = PyImport_FrozenModules = ctypes.POINTER(_frozen).in_dll(ctypes.pythonapi, name)
        for i in itertools.count():
            record = records[i]
            if record.name is None:
                break
            print(record.name)