Org Mode Babel - Interaktive Codeblockauswertung in Python

11

Ähnlich wie bei dieser Frage möchte ich (im Organisationsmodus) Python-Quellcodeblöcke auswerten, die "Eingabe" -Anweisungen enthalten, aber ich kann keine Möglichkeit finden, während der Auswertung eine interaktive Auswertung (mit Benutzereingaben) vorzunehmen oder ihr eine bekannte Eingabe zu geben im Voraus (zum Beispiel in einer Datei gespeichert).

Meine Einschränkung besteht darin, die inputAnweisung explizit zu verwenden , da all dies in einem Lehrbuch für Schüler enthalten sein sollte.

Beispiel für Code:

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

Ist es möglich, eine solche interaktive Auswertung durchzuführen oder zu simulieren (indem dem Quellcode eine gefälschte Eingabe gegeben wird)?

Lgen
quelle
Verwenden Sie den Organisationsmodus export, um Ihren Beispielcode für die Schüler in einem anderen Format zu generieren, z. B. HTML?
Melioratus
Die input () -Funktion von Python akzeptiert nur zitierten Text in einer Zeile, z. B. "Hallo" oder "Hallo \ nHallo \ nhowdy", richtig?
Melioratus
@ Melioratus Danke für Ihre Kommentare; Ja, ich verwende den Org-Modus-Export (nach LaTeX / pdf) und exportiere sowohl den Code als auch das Ergebnis. Sie können auch mehrzeiligen Text ("" "..." "") als Parameter für die Eingabefunktion verwenden. Mein Problem ist es, während der Ausführung des Codes Werte in die "Eingabe" -Funktion einzuführen.
Lgen
Danke für die Klarstellung! Ich werde eine Antwort veröffentlichen, die die gebildeten Programmierfunktionen verwendet, dh den nowebOrganisationsmodus, mit dem Sie Ihren Code mit Ergebnissen testen und exportieren können.
Melioratus
Vielen Dank, dies könnte eine Alternative zu der von John Kitchin vorgeschlagenen Lösung sein (möglicherweise wird der Verwicklungsschritt vermieden?).
Lgen

Antworten:

8

Hier ist ein alternativer Ansatz, bei dem eine nicht exportierte, verwickelte Datei verwendet wird, um die Eingabefunktion zu ersetzen.

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

Tipp: Drücken Sie C-cC-vtoder verwenden Sie den M-xorg-babel-tangleBefehl, um die Datei zu erstellen, dh zu verwirrenexample1.py .


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

Hinweis: Die example1.pyDatei, die aus dem vorherigen Python- SRCBlock erstellt wurde, wird mithilfe des integrierten Präambel- Headers und des Werts in den aktuellen Block importiert from example1 import *.

John Kitchin
quelle
Sehr interessante Lösung, danke. Ich akzeptiere es als Lösung und werde auch eine Variante vorschlagen, die auf dem Python-Generator basiert und systematisch ein "str" ​​-Objekt zurückgibt, um die Eingabefunktion (...) nachzuahmen.
Lgen
8

Bewerten Sie pythonCodeblöcke mithilfe der Lese- und Schreibprogrammierung im Organisationsmodus.

Verwenden Sie den :varHeader, um Variablen zuzuweisen und Ihren Code zu testen.

Hinweis: Falls gewünscht, verwenden Sie elisp (read-string "Prompt: ")und (read-number "Prompt: ")fordern Sie zur Eingabe von Benutzern in emacs auf.


Beispiel 1 - Drucken (a)

  • Zuweisen hello worldzu 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
    

Beispiel 2 - print(a + b)

  • Zuweisen 1zu a.

  • Zuweisen 2zu 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
    

Beispiel 3 - print(a,b,c)

  • Wenn Sie zur Value of aEingabe aufgefordert werdenThanks
  • Wenn Sie zur Value of bEingabe aufgefordert werden 4.
  • Wenn Sie zur Value of cEingabe aufgefordert werden 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
    

Wenn Sie Ihre Organisationsdatei exportieren, sollte die Ausgabe dem folgenden Beispiel ähneln


Beispiel 1 - print(a)

  • Zuweisen hello worldzu a.

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

Beispiel 2 - print(a + b)

  • Zuweisen 1zu a.
  • Zuweisen 2zu b.

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

Beispiel 3 - print(a,b,c)

  • Wenn Sie zur Value of aEingabe aufgefordert werdenThanks
  • Wenn Sie zur Value of bEingabe aufgefordert werden 4.
  • Wenn Sie zur Value of cEingabe aufgefordert werden 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
    


Dieser Code wurde mit
GNU Emacs 24.5.1 (x86_64-unknown-cygwin, GTK + Version 3.14.13)
Org-Mode Version: 8.3.2
und github getestet.

Melioratus
quelle
Sehr interessante Lösung; Es dauerte einige Zeit, bis ich verstanden hatte (ich bin es nicht gewohnt, Programmierkenntnisse zu erlangen), dass die Anweisungen im zweiten Python-Quellblock (z. B. a = Eingabe ('Wert von a')) nur Dokumentationstext waren und nicht als Anweisungen behandelt wurden.
Lgen
@Lgen - Danke! Die Lese- nowebund Schreibprogramme im Org-Modus sind erstaunlich und unglaublich nützlich! Bitte lassen Sie mich wissen, wenn Sie zusätzliche Codebeispiele wünschen. Wenn Sie etwas benötigen, das nicht gut in das Q & A-Format passt, poste ich gerne in meinem GitHub-Repository.
Melioratus
6

Ich denke nicht, dass es möglich ist, mit org-babel wirklich interaktive Python-Eingaben zu erhalten.

Sie können eine Präambel verwenden, um die Eingabefunktion neu zu definieren, sodass sie das zurückgibt, was Sie für die Verwendung der Eingabe simulieren möchten. Hier sieht es beispielsweise so aus, als hätte der Benutzer "3" eingegeben.

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

#+RESULTS:
: 3

Abhängig davon, was die Schüler sehen, die exportiert werden, sehen sie möglicherweise nicht, dass Sie dies getan haben.

John Kitchin
quelle
Vielen Dank, John, für die vorgeschlagene Antwort. Ich habe mich gefragt, ob es möglich ist, die Eingabefunktion im Codeblock auf mehrere Aufrufe auszudehnen (z. B. a = Eingabe ("Wert von a") b = Eingabe ("Wert von b")). Um das Texbook zu erstellen, verwende ich im Allgemeinen "und exportiere beide" in der Anweisung "# + BEGIN_SRC python", sodass diese Zeile im exportierten Text nicht sichtbar sein sollte.
Lgen
Wenn Sie eine Sitzung verwenden, ist es möglich: # + BEGIN_SRC Python: Sitzung: Exportiert keine def Eingabe (x): wenn x == 'Wert von a': Rückgabe 3 elif x == 'Wert von b': Rückgabe 4 # + END_SRC # + ERGEBNISSE: # + BEGIN_SRC Python: Ergebnisausgabe: Sitzung a = Eingabe ('Wert von a') b = Eingabe ('Wert von b') print (a + b) # + END_SRC # + ERGEBNISSE ::: >>> >>> 7
John Kitchin
2

Als Ergänzung zu John Kitchins Lösung schlage ich vor, einen Generator zu verwenden, um die aufeinanderfolgenden Werte bereitzustellen, die die input(...)Funktionen "füttern" und ein strObjekt systematisch zurückgeben.

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