pythonic way to optimize access to imported value?

Bengt Richter bokr at oz.net
Sat Nov 16 11:19:17 EST 2002


On 16 Nov 2002 02:18:41 -0500, aahz at pythoncraft.com (Aahz) wrote:

>In article <aqrig4$d2h$0 at 216.39.172.122>, Bengt Richter <bokr at oz.net> wrote:
>>
>>Here's a toy example. I just want to make a function that efficiently
>>uses (here just returns) something from a module. 
>
>Can you explain a bit more clearly what the purpose of this?

In a word, optimization.

Both speed and space.

The reason I focused on an item from a module is that typical usage
is to import the relevant module to make a global binding (e.g., globalmodulename)
and then to refer to the desired item  as globalmodulename.desireditem.

This is a fine mechanism when you want dynamic access to the current value of
something that may be getting updated, but if you want the value that was bound at the
time you are executing def myfunction (possibly with a view that the entire presence
of the module was temporary and would not be available for future access via a global
because it was not desired to hold it with a reference anywhere[1], but more likely
because it's just a constant, and you are avoiding magic numbers by referring to an
official definition module that may contain much else you don't need), then you want
to do the dereferencing at define time.

And for speed you don't want to execute the byte codes to do it more than once either,
nor do you want to execute byte codes for conditional setup/use of a cached value.
You want the first and all executions to see a preset binding generated at define time.

mkfoo was one way to do that now, but a simple presets: block would be clearer and handier.

[1] I assumed that it is possible to release all references to an imported module, so that
the garbage collector can eliminate it from memory, but that may have been a bad assumption.
sys.modules seem to get an entry whether you use

    import math
    pi = math.pi
    del math

or

    pi = __import__('math').pi

or even

    privatedir = {}
    exec 'pi = __import__("math").pi' in privatedir
    pi = privatedir['pi']
    del privatedir

Plus, deleting an entry in sys.modules seems risky, since you don't know who else
might be depending on it, even if you checked just before your import.

What does one have to do to "un-import" a module? (I'm talking about a simple case, not an
import with tricky side effects). I can think of a way to launder out references by a
two-pass python execution from the outside using temp files, but yuck.

As an example goal again, how would one do

    pi = __import__('math').pi

and wind up with *exactly* the same net effect as

    pi = 3.1415926535897931

with no math module stuff held by any reference (assume there wasn't any before the __import__).

BTW, the system seems to keep other references than sys.modules:

 [ 6:35] C:\pywk\cal>python -v
 # D:\python22\lib\site.pyc matches D:\python22\lib\site.py
 import site # precompiled from D:\python22\lib\site.pyc
 # D:\python22\lib\os.pyc matches D:\python22\lib\os.py
 import os # precompiled from D:\python22\lib\os.pyc
 import nt # builtin
 # D:\python22\lib\ntpath.pyc matches D:\python22\lib\ntpath.py
 import ntpath # precompiled from D:\python22\lib\ntpath.pyc
 # D:\python22\lib\stat.pyc matches D:\python22\lib\stat.py
 import stat # precompiled from D:\python22\lib\stat.pyc
 # D:\python22\lib\UserDict.pyc matches D:\python22\lib\UserDict.py
 import UserDict # precompiled from D:\python22\lib\UserDict.pyc
 # D:\python22\lib\copy_reg.pyc matches D:\python22\lib\copy_reg.py
 import copy_reg # precompiled from D:\python22\lib\copy_reg.pyc
 # D:\python22\lib\types.pyc matches D:\python22\lib\types.py
 import types # precompiled from D:\python22\lib\types.pyc
 # D:\python22\lib\__future__.pyc matches D:\python22\lib\__future__.py
 import __future__ # precompiled from D:\python22\lib\__future__.pyc
 Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
 Type "help", "copyright", "credits" or "license" for more information.
 >>>
 >>> import sys
 >>> sys.modules.get('math')
 >>> pi = __import__('math').pi
 import math # builtin
 >>> sys.modules.get('math')
 <module 'math' (built-in)>
 >>> del sys.modules['math']
 >>> sys.modules.get('math')
 >>> import math
 import math # previously loaded (math)
               ^^^^^^^^^^^^^^^^^^^^^^^^

Is there no way to do a private throwaway import?

Regards,
Bengt Richter



More information about the Python-list mailing list