2012-06-04 14 views
5

Me gustaría escribir múltiples funciones en el mismo módulo de Python, cada una de las cuales es una prueba de perfil por separado usando timeit, de modo que pueda usar un argumento de línea de comando para especificar uno para correr Un ejemplo ingenuo (profiling.py) sería:Podemos ejecutar múltiples funciones cada una con timeit en el mismo módulo

import sys 
import timeit 

def foo(): 

    setup = """ 
    import random 
    """ 

    foo_1 = """ 
    for i in range(1000): 
     random.randint(0, 99) + random.randint(0, 99) 
    """ 

    foo_2 = """ 
    for i in range(1000): 
     random.randint(0, 99) + random.randint(0, 99) 
    """ 

    foo_3 = """ 
    for i in range(1000): 
     random.randint(0, 99) + random.randint(0, 99) 
    """ 

    print 'foo_1', timeit.Timer(foo_1, setup).timeit(1000) 
    print 'foo_2', timeit.Timer(foo_2, setup).timeit(1000) 
    print 'foo_3', timeit.Timer(foo_3, setup).timeit(1000) 

if __name__ == '__main__': 
    if (len(sys.argv) > 1): 
     if (sys.argv[1] == 'foo'): 
      foo() 
    else: 
     print 'Which profiling do you want to run?' 
     print 'available:' 
     print ' foo' 

Sin embargo, cuando intento python profiling.py foo, me sale error como el siguiente:

foo_1 
Traceback (most recent call last): 
    File "profiling.py", line 32, in <module> 
    foo() 
    File "profiling.py", line 25, in foo 
    print 'foo_1', timeit.Timer(foo_1, setup).timeit(1000) 
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/timeit.py", line 136, in __init__ 
    code = compile(src, dummy_src_name, "exec") 
    File "<timeit-src>", line 6 
    _t0 = _timer() 
       ^
IndentationError: unindent does not match any outer indentation level 

He buscado por el error habitual sangría espacio/pestaña en el código, pero no encontró ninguno. Por lo tanto, me pregunto si es porque envuelvo una prueba timeit dentro de una función, ¿y esto no está permitido?

+1

¿Qué sucede si elimina los espacios en blanco de las cadenas que está pasando a timeit? (por ejemplo, 'foo_1 =" para i en el rango (1000): \ n random.randint (0, 99) + random.randint (0, 99) "') – mgilson

+0

¿Por casualidad copió y pegó esa línea? Muchas veces, al copiar y pegar, se encontrará con ese error debido a tabuladores o tamaños de pestañas que no coinciden como espacios en blanco. –

Respuesta

7

Esto funciona:

import sys 
import timeit 

def foo(): 

    setup = """ 
import random 
""" 

    foo_1 = """ 
for i in range(1000): 
    random.randint(0, 99) + random.randint(0, 99) 
""" 

    foo_2 = """ 
for i in range(1000): 
    random.randint(0, 99) + random.randint(0, 99) 
""" 

    foo_3 = """ 
for i in range(1000): 
    random.randint(0, 99) + random.randint(0, 99) 
""" 

    print 'foo_1', timeit.Timer(foo_1, setup).timeit(1000) 
    print 'foo_2', timeit.Timer(foo_2, setup).timeit(1000) 
    print 'foo_3', timeit.Timer(foo_3, setup).timeit(1000) 

if __name__ == '__main__': 
    if (len(sys.argv) > 1): 
     if (sys.argv[1] == 'foo'): 
      foo() 
    else: 
     print 'Which profiling do you want to run?' 
     print 'available:' 
     print ' foo' 

El problema es que sus cadenas que estás pasando como setup y foo_1, etc. están sangrados ya que les hemos alineado con su código sangrado dentro de la función . Sin embargo, cuando esa cadena se ejecuta por timeit, aumenta el error de indentación que ve porque el código no debe sangrarse. Esto es esencialmente lo mismo que pasaría si intentara ...

exec(" import sys") 

como lo primero en su sesión de intérprete interactivo.

+0

gracias por la sugerencia. Así que puedo solucionar el error haciendo 'setup =" "" import random "" "' (todo en una línea), ** sin ** hacer ningún cambio a foo_1. ¿Me pregunto porque? – MLister

+0

'timeit' debe hacer algo de" limpieza "en el argumento que se ejecutará, pero no en el código de configuración. – mgilson

+0

@MLister ¿Qué tiene de gracioso eso? No tiene ninguna sangría delante de su código de configuración, solo una nueva línea (las líneas en blanco son perfectamente aceptables en Python). – mgilson

0

mgilson dio una gran respuesta. Pero personalmente, encuentro que las líneas visualmente dedentadas en las cadenas de heredoc distraen. También rompe the vim python code folding I use.

se puede obtener el mismo efecto escribiendo las líneas por separado y unirse a ellos, así:

import sys 
import timeit 


def foo(): 

    setup = 'import random' 

    foo_1 = '\n'.join([ 
     'for i in range(1000):', 
     ' random.randint(0, 99) + random.randint(0, 99)', 
    ]) 

    foo_2 = '\n'.join([ 
     'for i in range(1000):', 
     ' random.randint(0, 99) + random.randint(0, 99)', 
    ]) 

    foo_3 = '\n'.join([ 
     'for i in range(1000):', 
     ' random.randint(0, 99) + random.randint(0, 99)', 
    ]) 

    print 'foo_1', timeit.Timer(foo_1, setup).timeit(1000) 
    print 'foo_2', timeit.Timer(foo_2, setup).timeit(1000) 
    print 'foo_3', timeit.Timer(foo_3, setup).timeit(1000) 

if __name__ == '__main__': 
    if (len(sys.argv) > 1): 
     if (sys.argv[1] == 'foo'): 
      foo() 
    else: 
     print 'Which profiling do you want to run?' 
     print 'available:' 
     print ' foo' 

se obtiene menos espacio en cada línea, pero la desventaja es la pena para mí.

Cuestiones relacionadas