[Pythonmac-SIG] Re: Weird import problem with PythonIDE on Mac (was
'import problem')
Chris Smith
smichr at bigfoot.com
Mon Apr 25 15:18:08 CEST 2005
On Friday, Apr 22, 2005, at 10:00 America/Chicago, Max Noel wrote:
>
>> Do you have a suggestion as to what can I give a module so it has
>> enough information to execute a function that resides in __main__?
>> Here is a visual of what is going on:
>>
>> ------__main__
>> def y1():
>> pass
>> import foo
>> foo.run(string_from_main) #what should I pass?
>>
>> ------external module, foo
>>
>> def run(string_from_main):
>> #
>> exec(string_from_main) #y1 is run as if it were in __main__
>>
>>
>> /c
>
> Python makes it easy to do because functions (and classes) are
> objects. Here:
>
> # in __main__
> def y1():
> pass
> import foo
> foo.run(y1)
>
>
> # in foo
> def run(functionFromMain):
> functionFromMain()
>
Yes, I know about this, but this is not the problem. The problem is
knowing what *strings* to pass to the timeit module so it can access a
function that is written in one's __main__. Basically, the timeit
module uses a template to construct a function which is (in the timeit
module) compiled and then executed. You get to send two strings: an
initialization string that is run once and the code string that appears
in a loop. Here, for example, is the function that is reconstructed
and run without success (in mac's pythonIDE:
###
def inner(_it, _timer):
from __main__ import y1 # I supplied this
_t0 = _timer()
for _i in _it:
y1() # and I supplied this
_t1 = _timer()
return _t1 - _t0
###
The way the IDE works, this import fails. There are two ways I have
found around the problem:
1) wrap the functions of __main__ into a triple quoted string and then
parsing it apart and sending it to timeit (not too elegant/pythonic):
### brute force passing of function to timeit
funcs='''
def y1():
print 'y1 executed'
def y2():
print 'y2 executed'
'''
for f in funcs.split('def'):
f = f.strip()
if not f:
continue
name = f.split('(')[0]
t=timeit.Timer('def '+f)
print name,t.timeit(1)
###
2) the other approach is to add an additional argument to the timeit
__init__ that accepts globals() from the calling program:
###
def __init__(self, stmt="pass", setup="pass", timer=default_timer,
glbls = globals):
"""Constructor. See class doc string.""" # changed
here - -^
self.timer = timer
stmt = reindent(stmt, 8)
setup = reindent(setup, 4)
src = template % {'stmt': stmt, 'setup': setup}
self.src = src # Save for traceback display
code = compile(src, dummy_src_name, "exec")
ns = {}
exec code in glbls, ns # and here
self.inner = ns["inner"]
###
Then __main__ can send functions like this:
###
def y1():
print 'y1 executed'
def y2():
print 'y2 executed'
for f in [y1,y2]:
func = f.__name__
t=timeit.Timer(stmt = "%s()" % func, glbls = globals())
print func, t.timeit(1)
###
{If you read to here, thanks. Is there a better way to accomplish this
with the current timeit module without modifying timeit? i.e. is there
another way to pass the needed information as a string that timeit's
created function can execute?}
/c
More information about the Pythonmac-SIG
mailing list