Org Mode Babel - Évaluation interactive de blocs de code en Python

12

De même à cette question, je voudrais évaluer (en mode org) des blocs de code source Python contenant des instructions "d'entrée" mais je ne trouve pas de moyen d'avoir une évaluation interactive (avec une entrée utilisateur) pendant l'évaluation ou de lui donner une entrée connue à l'avance (stocké dans un fichier par exemple).

Ma contrainte est d'utiliser explicitement l' inputinstruction puisque tout cela devrait être inclus dans un manuel pour les étudiants.

Exemple de code:

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

Est-il possible d'avoir une telle évaluation interactive ou de la simuler (en donnant au code source une fausse entrée)?

Lgen
la source
Allez-vous utiliser le mode organisationnel exportpour générer votre exemple de code pour les étudiants dans un autre format, par exemple html?
Melioratus
La fonction input () de Python ne prend que du texte entre guillemets sur une seule ligne, par exemple "bonjour" ou "salut \ nhello \ nhowdy", correct?
Melioratus
@Melioratus Merci pour vos commentaires; oui j'utilise l'export en mode org (vers LaTeX / pdf) et j'exporte à la fois le code et le résultat. Vous pouvez également utiliser du texte multilignes ("" "..." "") comme paramètre pour la fonction d'entrée. Mon problème est d'introduire des valeurs dans la fonction "entrée" lors de l'exécution du code.
Lgen
Merci pour la clarification! Je posterai une réponse qui utilise les fonctionnalités de programmation alphabétisées, c'est-à-dire nowebdu mode org qui vous permettra de tester et d'exporter votre code avec les résultats.
Melioratus
Merci, cela pourrait être une alternative à la solution proposée par John Kitchin (peut-être éviter l'étape d'enchevêtrement?).
Lgen

Réponses:

8

Voici une approche alternative qui utilise un fichier enchevêtré non exporté pour remplacer la fonction d'entrée.

#+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: 

Conseil: appuyez sur C-cC-vtou utilisez la M-xorg-babel-tanglecommande pour créer, c'est-à-dire enchevêtrer , le example1.pyfichier.


#+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

Remarque: le example1.pyfichier créé à partir du SRCbloc python précédent sera importé dans le bloc actuel à l'aide de l'en- tête builtin : preamble et de la valeur from example1 import *.

John Kitchin
la source
Solution très intéressante, merci. Je l'accepte comme solution et je proposerai également une variante basée sur le générateur python et renvoyant systématiquement un objet "str" ​​pour imiter la fonction d'entrée (...).
Lgen
8

Évaluez les pythonblocs de code à l'aide de la programmation alphabétisée en mode org.

Utilisez l'en- :vartête pour affecter des variables et tester votre code.

Remarque: Si vous le souhaitez, utilisez elisp (read-string "Prompt: ")et (read-number "Prompt: ")pour inviter l'utilisateur à entrer dans emacs.


Exemple 1 - impression (a)

  • Attribuer hello worldà 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
    

Exemple 2 - print(a + b)

  • Attribuer 1à a.

  • Attribuer 2à 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
    

Exemple 3 - print(a,b,c)

  • Lorsque vous êtes invité à Value of aentrerThanks
  • Lorsque vous êtes invité à Value of bentrer 4.
  • Lorsque vous êtes invité à Value of centrer 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
    

Lorsque vous exportez votre fichier org, la sortie doit ressembler à l'exemple ci-dessous


Exemple 1 - print(a)

  • Attribuer hello worldà a.

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

Exemple 2 - print(a + b)

  • Attribuer 1à a.
  • Attribuer 2à b.

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

Exemple 3 - print(a,b,c)

  • Lorsque vous êtes invité à Value of aentrerThanks
  • Lorsque vous êtes invité à Value of bentrer 4.
  • Lorsque vous êtes invité à Value of centrer 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
    


Ce code a été testé avec
GNU Emacs 24.5.1 (x86_64-unknown-cygwin, GTK + Version 3.14.13)
Version en mode org: 8.3.2
et github.

Melioratus
la source
Solution très intéressante; il m'a fallu du temps pour comprendre (je n'ai pas l'habitude de lire la programmation) que les instructions du deuxième bloc source python (par exemple a = input ('Value of a')) n'étaient qu'un texte de documentation et n'étaient pas traitées comme des instructions.
Lgen
@Lgen - Merci! La programmation alphabétisée noweb, en mode org, est incroyable et incroyablement utile! Veuillez me faire savoir si vous souhaitez des exemples de code supplémentaires. Si vous avez besoin de quelque chose qui ne rentre pas bien dans le format Q&A, je suis heureux de poster sur mon référentiel GitHub.
Melioratus
6

Je ne pense pas qu'il soit possible d'obtenir une entrée Python vraiment interactive avec org-babel.

Vous pouvez utiliser un préambule pour redéfinir la fonction d'entrée afin qu'elle renvoie ce que vous voulez simuler l'utilisation de l'entrée, par exemple ici, nous la faisons ressembler à l'utilisateur tapé "3".

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

#+RESULTS:
: 3

Selon ce que les élèves voient qui est exporté, ils peuvent ne pas voir que vous avez fait cela.

John Kitchin
la source
Merci John pour ta réponse proposée. Je me demandais s'il était possible de l'étendre à un appel multiple à la fonction d'entrée dans le bloc de code (par exemple a = entrée ("Valeur de a") b = entrée ("Valeur de b")). Pour construire le texbook, j'utilise généralement et ": export both" dans l'instruction "# + BEGIN_SRC python", donc cette ligne ne devrait pas être visible dans le texte exporté.
Lgen
Si vous utilisez une session, il est possible: # + BEGIN_SRC python: session: exporte none def def input (x): if x == 'Value of a': return 3 elif x == 'Value of b': return 4 # + END_SRC # + RÉSULTATS: # + BEGIN_SRC python: résultats sortie: session a = entrée ('Valeur de a') b = entrée ('Valeur de b') imprimer (a + b) # + END_SRC # + RÉSULTATS::: >>> >>> 7
John Kitchin
2

En complément de la solution de John Kitchin, je propose d'utiliser un générateur pour fournir les valeurs successives qui "alimenteront" les input(...)fonctions et retourner strsystématiquement un objet.

#+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
la source