Org Mode Babel - Evaluación de bloque de código interactivo en Python

12

De manera similar a esta pregunta, me gustaría evaluar (en modo org.) Los bloques de código fuente de Python que contienen instrucciones de "entrada", pero no puedo encontrar una manera de tener una evaluación interactiva (con la entrada del usuario) durante la evaluación o darle alguna entrada conocida por adelantado (almacenado en un archivo, por ejemplo).

Mi restricción es usar explícitamente la inputinstrucción ya que todo esto debería incluirse en un libro de texto para estudiantes.

Ejemplo de código:

#+BEGIN_SRC python :results output 
a= input("Value") 
print(a)
#+END_SRC

¿Es posible tener una evaluación tan interactiva o simularla (dando al código fuente una entrada falsa)?

Lgen
fuente
¿Utilizará el modo org exportpara generar su código de ejemplo para los estudiantes en algún otro formato, por ejemplo, html?
Melioratus
La función input () de Python solo toma el texto citado en una sola línea, por ejemplo, "hola" o "hola \ nhello \ nhowdy", ¿correcto?
Melioratus
@Melioratus Gracias por sus comentarios; Sí, uso la exportación en modo org (a LaTeX / pdf) y exporto tanto el código como el resultado. También puede usar texto de líneas múltiples ("" "..." "") como parámetro para la función de entrada. Mi problema es introducir valores a la función "input" durante la ejecución del código.
Lgen
¡Gracias por la aclaración! Publicaré una respuesta que utiliza las funciones de programación alfabetizadas, es decir noweb, del modo org que le permitirá probar y exportar su código con resultados.
Melioratus
Gracias, esta podría ser una alternativa a la solución propuesta por John Kitchin (¿puede estar evitando el paso de enredo?).
Lgen

Respuestas:

8

Aquí hay un enfoque alternativo que utiliza un archivo enredado no exportado para reemplazar la función de entrada.

#+BEGIN_SRC python :session :exports none :tangle example1.py
def input(x): 
    if x == 'Value of a':
        return 3
    elif x == 'Value of b':
        return 4 

#+END_SRC 

#+RESULTS: 

Consejo: Presione C-cC-vto use el M-xorg-babel-tanglecomando para crear, es decir , enredar , el example1.pyarchivo.


#+BEGIN_SRC python :results output :preamble from example1 import *
a = input('Value of a')
b = input('Value of b')
print(a + b) 
#+END_SRC 

#+RESULTS:
: 7

Nota: El example1.pyarchivo que se creó a partir del SRCbloque anterior de Python se importará al bloque actual utilizando el encabezado preámbulo y el valor from example1 import *.

John Kitchin
fuente
Solución muy interesante, gracias. Lo acepto como la solución y también propondré una variante basada en el generador de Python y devolviendo sistemáticamente un objeto "str" ​​para imitar la función de entrada (...).
Lgen
8

Evaluar pythonbloques de código utilizando programación alfabetizada en modo org.

Use el :varencabezado para asignar variables y probar su código.

Nota: Si lo desea, use elisp (read-string "Prompt: ")y (read-number "Prompt: ")solicite la entrada del usuario dentro de emacs.


Ejemplo 1 - imprimir (a)

  • Asignar hello worlda a.


    #+name: ex1-code  
    #+header: :var a="hello world"  
    #+begin_src python :results verbatim replace output :exports results  
      print(a)  
    #+end_src
    
    #+begin_src python :eval never :exports code :noweb yes   
      a = input('Value of a')  
      <<ex1-code>>  
    #+end_src  
    
    #+results: ex1-code
    : hello world
    

Ejemplo 2 - print(a + b)

  • Asignar 1a a.

  • Asignar 2a b.


    #+name: ex2-code
    #+header: :var a=1 
    #+header: :var b=2 
    #+begin_src python :results replace output  :exports results 
      print(a + b)
    #+end_src
    
    #+begin_src python :eval never :exports code :noweb yes 
      a = input('Value of a')
      b = input('Value of b')
      <<ex2-code>>
    #+end_src  
    
    #+results: ex2-code
    : 3
    

Ejemplo 3 - print(a,b,c)

  • Cuando se le solicite Value of aingresarThanks
  • Cuando se le solicite Value of bingresar 4.
  • Cuando se le solicite Value of cingresar your question.


    #+NAME: ex3-code
    #+header: :var a=(read-string "Value of a ") 
    #+header: :var b=(read-number "Value of b ") 
    #+header: :var c=(read-string "Value of c ") 
    #+begin_src python :results replace output   :exports results 
      print a,b,c
    #+end_src  
    
    #+begin_src python :eval never :exports code :noweb yes 
      a = input('Value of a')
      b = input('Value of b')
      c = input('Value of c')
      <<ex3-code>>
    #+end_src  
    
    #+results: ex3-code
    : Thanks 4 your question
    

Cuando exporta su archivo de organización, la salida debería ser similar al ejemplo a continuación


Ejemplo 1 - print(a)

  • Asignar hello worlda a.

    a = input('Value of a')
    print(a)
    
    hello world
    

Ejemplo 2 - print(a + b)

  • Asignar 1a a.
  • Asignar 2a b.

    a = input('Value of a')
    b = input('Value of b')
    print(a + b)
    
    3
    

Ejemplo 3 - print(a,b,c)

  • Cuando se le solicite Value of aingresarThanks
  • Cuando se le solicite Value of bingresar 4.
  • Cuando se le solicite Value of cingresar your question.

    a = input('Value of a')
    b = input('Value of b')
    c = input('Value of c')
    print a,b,c
    
    Thanks 4 your question
    


Este código se probó con
GNU Emacs 24.5.1 (x86_64-unknown-cygwin, GTK + Versión 3.14.13) Versión
Org-Mode: 8.3.2
y github.

Melioratus
fuente
Solución muy interesante; Me tomó tiempo entender (no estoy acostumbrado a la programación alfabetizada) que las instrucciones en el segundo bloque fuente de Python (por ejemplo, a = input ('Valor de a')) eran solo texto de documentación y no fueron tratadas como instrucciones.
Lgen
@Lgen - ¡Gracias! ¡La programación alfabetizada noweb, en las funciones del modo org es increíble e increíblemente útil! Avíseme si desea ejemplos de código adicionales. Si necesita algo que no encaja bien en el formato de preguntas y respuestas, me complace publicarlo en mi repositorio de GitHub.
Melioratus
6

No creo que sea posible obtener una entrada de Python verdaderamente interactiva con org-babel.

Puede usar un preámbulo para redefinir la función de entrada para que devuelva lo que desea simular el uso de la entrada, por ejemplo, aquí hacemos que parezca que el usuario escribió "3".

#+BEGIN_SRC python :results output :preamble def input(x): return 3
a = input("value ")
print(a)
#+END_SRC

#+RESULTS:
: 3

Dependiendo de lo que los alumnos vean que se exporta, es posible que no vean que usted ha hecho esto.

John Kitchin
fuente
Gracias John por tu respuesta propuesta. Me preguntaba si es posible extenderlo a una llamada múltiple a la función de entrada en el bloque de código (por ejemplo, a = input ("Valor de a") b = input ("Valor de b")). Para compilar el libro de texto, generalmente uso y ": exportar ambos" en la declaración "# + BEGIN_SRC python" para que esta línea no sea visible en el texto exportado.
Lgen
Si usa una sesión, es posible: # + BEGIN_SRC python: sesión: no exporta ninguna entrada def (x): si x == 'Valor de a': devuelve 3 elif x == 'Valor de b': devuelve 4 # + END_SRC # + RESULTADOS: # + BEGIN_SRC python: salida de resultados: sesión a = input ('Valor de a') b = input ('Valor de b') print (a + b) # + END_SRC # + RESULTADOS::: >>> >>> 7
John Kitchin
2

Como complemento de la solución de John Kitchin, propongo usar un generador para proporcionar los valores sucesivos que "alimentarán" las input(...)funciones y devolver un strobjeto sistemáticamente.

#+BEGIN_SRC python :session :exports none :tangle example2.py :results none
def generate(lst):
    for element in lst:
        yield str(element)

generator =  generate(["Thanks",4,"your help"])

def input(x):
     return generator.__next__()
#+END_SRC 


#+BEGIN_SRC python :results output :preamble from example2 import * :exports both
a = input('Value of a')
b = input('Value of b')
c = input('Value of c')
print(a,b,c)
#+END_SRC 
Lgen
fuente