显示Python模块是否从字节码加载



我正在尝试调试Hy的字节码使用。特别是,每次导入模块时,我都希望看到实际导入模块的路径,无论是源代码还是字节码。在底层,Hy通过importlib管理模块。它不显式地读取或写入字节码;这是由importlib.machinery.SourceFileLoader处理的。所以看起来我想做的是给Python的导入系统打补丁,让它在每次导入发生时打印导入路径。我该怎么做呢?一旦我理解了如何为Python做这件事,我应该就能弄清楚如何为Hy做这件事了。

不涉及编码的最简单方法是使用两个(!)详细标志启动Python:

python -vv myscript.py

,你会得到大量的输出,包括所有的import语句和所有的文件,Python试图访问以加载模块。在这个例子中,我有一个简单的python脚本,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' 
[...]

或者更复杂:您可以更改import语句本身。为此,您可以覆盖__import__,它由import语句本身调用。这样就可以打印出import实际打开的所有文件。

似乎是一个很好的选择是动态地将importlib.machinery.SourceFileLoader(fullname, path)importlib.machinery.SourcelessFileLoader(fullname, path)补丁到每个打印或写入变量(a)调用方法和(b)传递给函数的参数。

如果你需要做的是:

我想看到它实际导入的路径,无论是源代码还是字节码

并且您不需要导入"正常工作",也许您可以做类似的修改版本。例如,我很快修改了他们的示例代码来得到这个,我没有测试它,所以它可能不能完全工作,但它应该让你在正确的轨道上:

# custom class to be the mock return value
class MockSourceLoader:
# mock SourceFileLoader method always returns that the module was loaded from source and its path
def SourceFileLoader(fullname, path):
return {"load type": "source", "fullname": fullname, "path": path}
def check_how_imported(monkeypatch):
# Any arguments may be passed and mock_get() will always return our
# mocked object
def mock_get(*args, **kwargs):
return MockSourceLoader
# apply the monkeypatch
monkeypatch.setattr(importlib.machinery, SourceFileLoader, SourceFileLoader)

您当然可以为SourcelessFileLoader的无源文件加载提供类似的模拟

参考:

  • https://docs.python.org/3/library/importlib.html: ~:文本= importlib.machinery.SourceFileLoader (fullname % 2 c % 20路径)% C2%B6
  • https://docs.python.org/3/library/importlib.html: ~:文本= importlib.machinery.SourcelessFileLoader (fullname % 2 c % 20路径)

最新更新