I'm trying to get my programs memory footprint under control. I thought I'd start with the imports, as I'm only using 3-4 functions out of the rather large PyObjC
library. However, I was a little surprised to see that importing specific pieces of a larger module had zero bearing on what was actually loaded into memory.
loading the entire Quartz.CoreGraphics library on 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
It pulls in the entire library at almost 19MB.
Trying to only pull in what I need gives the same 19MB results:
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
So, it seems that specific imports have no bearing on what actually gets loaded.
Needing only a small handful of functions from an otherwise huge module seems like it would be a common use-case. Is there any way to load only what I need from a module into memory, or is this just the consequence of using external libraries?
This happens because when Python imports a module, it runs all the code in that module. After running the module it takes whatever variables were defined in that module, and it puts them on the module object, which in our case is salutations .
When a module is first imported, Python searches for the module and if found, it creates a module object 1, initializing it. If the named module cannot be found, a ModuleNotFoundError is raised. Python implements various strategies to search for the named module when the import machinery is invoked.
The import Statement A module is loaded only once, regardless of the number of times it is imported. This prevents the module execution from happening over and over again if multiple imports occur.
In Python, you use the import keyword to make code in one module available in another. Imports in Python are important for structuring your code effectively. Using imports properly will make you more productive, allowing you to reuse code while keeping your projects maintainable.
That's just how module loading works. The runtime maintains a collection of loaded modules, so the whole module is reachable even if you've only imported a few symbols. This has two desirable consequences:
It's also fairly inevitable if you consider that any function in the module can access the module namespace, either directly by using names from it or indirectly via globals()
, sys.modules[__name__]
, eval
, or whatever. So barring some clever optimization to prove that particular functions don't do this (which Python implementations don't generally bother with), the whole module namespace has to be in memory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With