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

发布于 2025-02-01 11:44:17 字数 348 浏览 3 评论 0 原文

我正在尝试调试 hy 使用bytecode。特别是,每次导入模块时,我都想查看其实际导入的路径,无论是源还是字节码。在引擎盖下,HY用 ementlib 管理模块。它没有明确读取或编写字节;这是由 ementlib.machinery.sourcefileleleoader 来照顾的。因此,看来我想做的是每次导入时,猴子斑点Python的导入系统都可以打印导入路径。我该怎么做?一旦我了解如何为python做,我应该能够弄清楚如何做到这一点。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情愿 2025-02-08 11:44:17

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

python -vv myscript.py

您将获得大量输出,包括所有导入语句和所有文件Python试图访问以加载模块。在此示例中,我有一个简单的python脚本,可以导入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 __ import __ ,由导入语句本身调用。这样,您可以打印出所有文件导入实际打开。

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.

十级心震 2025-02-08 11:44:17

似乎是一个不错的选择是动态修补 ementlib.machinery.sourcefileleleoader(fullname,path) and ementlib.machinery.sourcelessfileleleoader(fullname,path,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)

您当然会为

>参考的

Seems like a good option would be to dynamically patch importlib.machinery.SourceFileLoader(fullname, path) and importlib.machinery.SourcelessFileLoader(fullname, path) to each print or write to a variable (a) the calling method and (b) the argument passed to the function.

If all you need to do is:

I want to see the path it was actually imported from, whether source or bytecode

And you don't need the import to "work properly", perhaps you can do a modified version of something like this. For example, I quickly modified their sample code to get this, I have not tested it so it may not work exactly, but it should get you on the right track:

# 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)

You would of course provide a similar mock for Sourceless file loading for SourcelessFileLoader

For reference:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文