Search code examples
pythonbytecodehy

Show whether a Python module is loaded from bytecode


I'm trying to debug Hy's use of bytecode. In particular, each time a module is imported, I want to see the path it was actually imported from, whether source or bytecode. Under the hood, Hy manages modules with importlib. It doesn't explicitly read or write bytecode; that's taken care of by importlib.machinery.SourceFileLoader. So it looks like what I want to do is monkey-patch Python's importing system to print the import path each time an import happens. How can I do that? I should be able to figure out how to do it for Hy once I understand how to do it for Python.


Solution

  • The easiest way that does not involve coding, is to start Python with two(!) verbose flags:

    python -vv myscript.py
    

    you'll get a lot of output, including all the import statements and all the files Python tries to access in order to load the module. In this example I have a simple python script that does import json:

    lots of output!
    [...]
    # trying /tmp/json.cpython-310-x86_64-linux-gnu.so                                                                                                                                              
    # trying /tmp/json.abi3.so                                                                                                                                                                      
    # trying /tmp/json.so                                                                                                                                                                           
    # trying /tmp/json.py                                                                                                                                                                           
    # trying /tmp/json.pyc                                                                                                                                                                          
    # /usr/lib/python3.10/json/__pycache__/__init__.cpython-310.pyc matches /usr/lib/python3.10/json/__init__.py                                                                                    
    # code object from '/usr/lib/python3.10/json/__pycache__/__init__.cpython-310.pyc' 
    [...]
    

    Alternatively but more complex: you could change the import statement itself. For that, you can overwrite __import__, which is invoked by the import statement itself. This way you could print out all the files import actually opens.