Importing a file into another module's namespace

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Wed Apr 29 00:41:39 EDT 2009


On Tue, 28 Apr 2009 17:26:22 -0500, Gary Oberbrunner wrote:

> Hi Steven (and MRAB), thanks for this idea.  This looks pretty
> straightforward and useful.  I also heard of another way via googling
> around; see what you think of this.  For example's sake this code just
> adds stuff to the os.path module (but I could pick any module not under
> my control).  For fun I have the code in a string rather than a file,
> but I think it works either way.
> 
> import sys
> import os.path
>  
> f='''
> def Foo(x):
>   print "%s: Foo!"%x
> Bar=123
> '''
> 
> # now the magic two lines:
> m=sys.modules['os.path']
> exec f in m.__dict__
> 
> # test:
> os.path.Foo("Gary")
> print os.path.Bar
> 
> ==== cut =================
> 
> What do you think?  Better or worse than looping over dir()?  


Definitely worse, but then I'm biased against solutions involving exec, 
execfile or eval unless they've been approved by people much smarter than 
me.


> Probably faster and less memory, 

Probably not. It's quite hard to intuit Python's speed and memory usage, 
at least not without a *lot* of experience. If you're like me, and grew 
up using a low-level language like C or Pascal, your intuitions are 
probably going to be backwards.

In my experience, using exec is significantly slower than executing the 
code directly, or at least more noticeably slower because you pay the 
cost of compiling the string every time you run the code instead of just 
once. But without testing, my guess is meaningless. However, I will give 
you this one data point:


>>> from timeit import Timer
>>> Timer("pass").repeat()
[0.059679031372070312, 0.059665203094482422, 0.059659957885742188]
>>> Timer("exec 'pass'").repeat()
[13.1195969581604, 13.000137090682983, 13.537813901901245]


That's about 25 times slower.

However, in your specific case, whichever solution is slower, does it 
matter that a piece of code that runs *once* takes 0.00025 second instead 
of 0.00001 second? Probably not. What's more important in that case is 
ease of maintenance and readability, and on that note, I think the exec 
solution loses significantly, if for no other reason that syntax 
highlighting doesn't work in your editor if you disguise functions inside 
strings.



-- 
Steven



More information about the Python-list mailing list