导入时,为什么即使只指定了特定部分,也要加载整个模块?

2024-04-27 02:37:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在努力控制我的程序内存占用。我想我应该从导入开始,因为我只使用相当大的PyObjC库中的3-4个函数。然而,我有点惊讶地看到,导入一个更大模块的特定片段与实际加载到内存中的内容没有任何关系。你知道吗

内存探查器输出

加载整个石英.岩芯图形OSX上的库:

Line #    Mem usage    Increment   Line Contents
================================================
    77                             @profile 
    78     7.953 MB     0.000 MB   def test_import_all():
    79    26.734 MB    18.781 MB    import Quartz.CoreGraphics as CG

它以将近19MB的速度把整个图书馆拉了进来。你知道吗

尝试只拉入我需要的内容会得到相同的19MB结果:

Line #    Mem usage    Increment   Line Contents
================================================
    82                             @profile
    83     7.941 MB     0.000 MB   def test_import_some():
    84    26.727 MB    18.785 MB    from Quartz.CoreGraphics import CGImageGetWidth 

所以,似乎特定的进口对实际装载的货物没有影响。你知道吗

从一个庞大的模块中只需要一小部分函数,这似乎是一个常见的用例。有没有办法只把我需要的从模块中加载到内存中,或者这仅仅是使用外部库的结果?你知道吗


Tags: 模块函数内存testimport内容defline
2条回答

不,没有,因为即使您认为您只需要一个函数,该函数也可能需要模块中的其他函数(或类等)。模块是导入可以加载的最小代码单元。如果模块可以被分成多个独立的部分,并且它足够大,这将对性能产生影响,那么它应该是。否则,您不能只导入部分和/或可以导入也无所谓。你知道吗

这就是模块加载的工作原理。运行时维护已加载模块的集合,因此即使只导入了几个符号,也可以访问整个模块。这有两个可取的结果:

  • 同一模块的未来进口很快。你知道吗
  • 任何在模块级有副作用的代码只执行一次(除非重新加载模块),而不是根据模块的哪些位在哪些位置导入而执行可变的次数。你知道吗

如果您认为模块中的任何函数都可以访问模块名称空间,那么这也是不可避免的,可以直接使用模块名称空间中的名称,也可以通过globals()sys.modules[__name__]eval或其他方式间接访问。因此,除非通过一些巧妙的优化来证明特定函数不能做到这一点(Python实现通常不需要考虑),否则整个模块名称空间必须在内存中。你知道吗

相关问题 更多 >