显示 Python 模块是否从字节码加载
Show whether a Python module is loaded from bytecode
我正在尝试调试 Hy 对字节码的使用。特别是,每次导入模块时,我都想查看它实际导入的路径,无论是源代码还是字节码。在幕后,Hy 使用 importlib
管理模块。它没有明确地读取或写入字节码;这是由 importlib.machinery.SourceFileLoader
负责的。所以看起来我想要做的是 monkey-patch Python 的导入系统在每次导入发生时打印导入路径。我怎样才能做到这一点?一旦我了解如何为 Python.
做这件事,我应该能够弄清楚如何为 Hy 做这件事
似乎一个不错的选择是动态修补 importlib.machinery.SourceFileLoader(fullname, path)
和 importlib.machinery.SourcelessFileLoader(fullname, path)
到每个打印或写入变量 (a) 调用方法和 (b) 传递给函数的参数.
如果您只需要:
I want to see the path it was actually imported from, whether source or bytecode
而且你不需要导入来“正常工作”,也许你可以做一个类似 this 的修改版本。例如,我快速修改了他们的示例代码来得到这个,我没有测试过所以它可能无法正常工作,但它应该让你走上正轨:
# 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
的无源文件加载提供类似的模拟
供参考:
不涉及编码的最简单方法是 Python 开始时使用两个(!)详细标志:
python -vv myscript.py
您会得到很多输出,包括所有导入语句和所有 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
实际打开的所有文件。
我正在尝试调试 Hy 对字节码的使用。特别是,每次导入模块时,我都想查看它实际导入的路径,无论是源代码还是字节码。在幕后,Hy 使用 importlib
管理模块。它没有明确地读取或写入字节码;这是由 importlib.machinery.SourceFileLoader
负责的。所以看起来我想要做的是 monkey-patch Python 的导入系统在每次导入发生时打印导入路径。我怎样才能做到这一点?一旦我了解如何为 Python.
似乎一个不错的选择是动态修补 importlib.machinery.SourceFileLoader(fullname, path)
和 importlib.machinery.SourcelessFileLoader(fullname, path)
到每个打印或写入变量 (a) 调用方法和 (b) 传递给函数的参数.
如果您只需要:
I want to see the path it was actually imported from, whether source or bytecode
而且你不需要导入来“正常工作”,也许你可以做一个类似 this 的修改版本。例如,我快速修改了他们的示例代码来得到这个,我没有测试过所以它可能无法正常工作,但它应该让你走上正轨:
# 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
供参考:
不涉及编码的最简单方法是 Python 开始时使用两个(!)详细标志:
python -vv myscript.py
您会得到很多输出,包括所有导入语句和所有 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
实际打开的所有文件。