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

_______________________________________________
Pythonmac-SIG maillist  -  Pythonmac-SIG@python.org
http://mail.python.org/mailman/listinfo/pythonmac-sig

Reply via email to