¿Por qué no puedo pegar la salida de Pythons REPL sin edición manual?

Una gran cantidad de código de ejemplo de Python muestra la salida del REPL de Python, por ejemplo:

>>> class eg(object): ... def __init__(self, name): ... self.name = name ... def hi(self): ... print "Hi %s" % (self.name) ... >>> greeter = eg("Bob") >>> greeter.hi() Hi Bob >>> 

Ahora, lo más obvio que quieres hacer es ejecutar el código anterior … así que ejecuté “python” y pegué el texto anterior …

 >>> >>> class eg(object): File "", line 1 >>> class eg(object): ^ SyntaxError: invalid syntax >>> ... def __init__(self, name): File "", line 1 ... def __init__(self, name): ^ 

El código está roto!? ..

Para que funcione, tendría que:

  • copie y pegue las líneas de una en una, asegurándose de que copie correctamente la sangría. Si lo arruinas (por ejemplo, te pierdes un espacio inicial, debes comenzar todo de nuevo)
  • usa un editor de texto para eliminar >>> y ... , luego vuelve a pegar

No es un gran problema, pero dado el código de ejemplo que se presenta en este formato, parece extraño que tenga que hacer esto …

Cómo ejecutar / adoptar “la salida de Pythons REPL”

  • Usa el shell de IPython

     In [99]: %cpaste Pasting code; enter '--' alone on the line to stop. :>>> class eg(object): :... def __init__(self, name): :... self.name = name :... def hi(self): :... print "Hi %s" % (self.name) :... :>>> greeter = eg("Bob") :>>> greeter.hi() :-- Hi Bob 
  • Use un editor de texto capaz (por ejemplo, Cx rk mata la región rectangular en Emacs )

  • Usa el módulo doctest

Copie sin el indicador de comandos de shell en primer lugar (aunque no sé cómo hacerlo en Google Chrome, por ejemplo).

¿Por qué se utiliza el formato doctest?

Guarde lo siguiente en documentation.txt :

 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
 eiusmod tempor incididunt ut labore et dolore magna aliqua.  Anuncio de utilidad
 minim veniam, quis nostrud ejercicio ullamco laboris nisi ut
 Aliquip ex ea commodo consecuat. 

 >>> clase por ejemplo (objeto):
 ... def __init __ (self, name):
 ... self.name = name
 ... def hi (self):
 ... imprima "Hola% s"% (nombre propio)
 ... 
 >>> greeter = por ejemplo ("Bob")
 >>> greeter.hi ()
 Hola Bob
 >>>

 Duis aute ire dolor en reprehenderit en voluptate velit esse cillum
 Dolore eu fugiat nulla pariatur.  Excepteur sint occaecat cupidatat non
 proident, sunt in culpa qui officia deserunt mollit anim id est
 laborum

Correr:

 $ python -c "import doctest; doctest.testfile('documentation.txt')" -v 

Salida:

 Trying: class eg(object): def __init__(self, name): self.name = name def hi(self): print "Hi %s" % (self.name) Expecting nothing ok Trying: greeter = eg("Bob") Expecting nothing ok Trying: greeter.hi() Expecting: Hi Bob ok 1 items passed all tests: 3 tests in doctest.txt 3 tests in 1 items. 3 passed and 0 failed. Test passed. 

Si agrega el siguiente fragmento de código al final de su módulo, probará todo el código en sus cadenas de documentación:

 if __name__=="__main__": import doctest; doctest.testmod() 

QED

No sé si hay una buena solución para esto. Idealmente, habría alguna forma de modificar el comportamiento del intérprete para aceptar copiar / pegar información de este tipo. Aquí hay algunas sugerencias alternativas:

Use comillas triples para guardar el ejemplo en una cadena. Luego, use exec:

 >>> def chomp_prompt(s): return '\n'.join(ln[4:] for ln in s.splitlines()) ... >>> dirty = """>>> class eg(object): ... ... def __init__(self, name): ... ... self.name = name ... ... def hi(self): ... ... print "Hi %s" % (self.name) ... ... ... >>> greeter = eg("Bob") ... >>> greeter.hi() ... """ >>> clean = chomp_prompt(dirty) >>> exec clean Hi Bob >>> 

No solo mi solución encaja en una sola línea (por lo que será fácil para usted copiarla y pegarla en el intérprete), funciona en el ejemplo anterior: D:

 >>> s = r'''>>> def chomp_prompt(s): return '\n'.join(ln[4:] for ln in s.splitlines()) ... ... ... >>> dirty = """>>> class eg(object): ... ... ... def __init__(self, name): ... ... ... self.name = name ... ... ... def hi(self): ... ... ... print "Hi %s" % (self.name) ... ... ... ... ... >>> greeter = eg("Bob") ... ... >>> greeter.hi() ... ... """ ... >>> clean = chomp_prompt(dirty) ... >>> exec clean''' >>> s2 = chomp_prompt(s) >>> exec s2 Hi Bob 

Mi segunda sugerencia es mirar la capacidad de ipython para abrir un editor para ti y ejecutar lo que ingresaste allí después de que hayas terminado de editar:

http://ipython.scipy.org/doc/rel-0.9.1/html/interactive/tutorial.html#source-code-handling-tips

Si configura emacs como su editor, sé que tiene la capacidad de eliminar un rectángulo de texto (probablemente pueda adivinar el comando: Mx delete-rectangle), que funcionaría perfectamente para deshacerse de esas molestas indicaciones. Estoy seguro que muchos otros editores tienen esto también.

Las preguntas “por qué” rara vez tienen respuestas útiles.

Por ejemplo, si dije que la razón por la que se evitó una demanda compleja por infracción de propiedad intelectual, ¿qué hace eso? Nada. Todavía tienes que dejar de copiar y pegar y empezar a pensar y escribir.

O, por ejemplo, si dije que la razón por la que se dio aquí , no hay nada que se pueda poner en práctica. El problema es que los ejemplos se deben escribir en lugar de cortar y pegar. Y ese problema no se resuelve con esta información.

De hecho, el problema es realmente “quiero copiar y pegar sin pensar y escribir tanto, ¿cómo puedo hacer eso?” Y la respuesta es la misma.

No puede copiar y pegar la sesión interactiva (excepto en doctest comments). Tienes que escribirlo. Lo siento.

El código se presenta de esta manera, ya que está destinado a ser un proceso paso a paso. Los tres caracteres que ves “>>>” son los del IDE de Python, pero parece que ya lo sabes. Cuando tenga acceso a una consola o shell, y escriba python, obtendrá algo como esto.

 % python Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> 

Así que realmente tómalo como una herramienta educativa. 🙂