Org Mode Babel - Интерактивная оценка кода блока в Python

12

Аналогично этому вопросу я хотел бы оценить (в режиме org) блоки исходного кода Python, содержащие инструкции «input», но я не могу найти способ провести интерактивную оценку (с пользовательским вводом) во время оценки или дать ему какой-либо известный ввод заранее (хранится в файле, например).

Мое ограничение состоит в том, чтобы использовать inputинструкцию явно, поскольку все это должно быть включено в учебник для студентов.

Пример кода:

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

Можно ли провести такую ​​интерактивную оценку или смоделировать ее (предоставив исходному коду поддельный ввод)?

Lgen
источник
Будете ли вы использовать org-mode exportдля генерации вашего примера кода для студентов в каком-либо другом формате, например, html?
Мелиоратус
Функция ввода () Python принимает только заключенный в кавычки текст в одну строку, например, "привет" или "привет \ nhello \ nhowdy", правильно?
Мелиоратус
@Melioratus Thaks за ваши комментарии; да, я использую экспорт в режиме org (в LaTeX / pdf) и экспортирую как код, так и результат. Вы также можете использовать многострочный ("" "..." "") текст в качестве параметра для функции ввода. Моя проблема состоит в том, чтобы ввести значения в функцию ввода во время выполнения кода.
Lgen
Благодарю за разъяснение! Я опубликую ответ, который использует возможности грамотного программирования, т. nowebЕ. Режима org, который позволит вам тестировать и экспортировать свой код с результатами.
Мелиоратус
Спасибо, это может быть альтернативой решению, предложенному Джоном Китчином (может быть, избежать путаницы?).
Lgen

Ответы:

8

Вот альтернативный подход, который использует неэкспортированный, запутанный файл, чтобы заменить функцию ввода.

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

Совет: нажмите C-cC-vtили используйте M-xorg-babel-tangleкоманду для создания, т. Е. Связывания , example1.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

Примечание . example1.pyФайл, созданный из предыдущего SRCблока python, будет импортирован в текущий блок с использованием заголовка встроенного преамбулы и значения from example1 import *.

Джон Китчин
источник
Очень интересное решение, спасибо. Я принимаю это как решение, и я также предложу вариант, основанный на генераторе питона и систематически возвращающий объект "str" ​​для имитации функции ввода (...).
Lgen
8

Оцените pythonблоки кода, используя грамотное программирование в режиме org.

Используйте :varзаголовок, чтобы назначить переменные и проверить ваш код.

Примечание: При желании используйте elisp (read-string "Prompt: ")и (read-number "Prompt: ")для запроса ввода пользователя внутри emacs.


Пример 1 - печать (а)

  • Назначают 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
    

Пример 2 - print(a + b)

  • Назначают 1в a.

  • Назначают 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
    

Пример 3 - print(a,b,c)

  • Когда предложено Value of aввестиThanks
  • Когда будет предложено Value of bввести 4.
  • Когда будет предложено Value of cввести 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
    

Когда вы экспортируете свой файл org, вывод должен выглядеть примерно так, как показано ниже


Пример 1 - print(a)

  • Назначают hello worldв a.

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

Пример 2 - print(a + b)

  • Назначают 1в a.
  • Назначают 2в b.

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

Пример 3 - print(a,b,c)

  • Когда предложено Value of aввестиThanks
  • Когда будет предложено Value of bввести 4.
  • Когда будет предложено Value of cввести 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
    


Этот код был протестирован с
GNU Emacs 24.5.1 (x86_64-unknown-cygwin, GTK + версия 3.14.13) Версия в режиме
Org: 8.3.2
и github.

Melioratus
источник
Очень интересное решение; Мне потребовалось время, чтобы понять (я не привык к грамотному программированию), что инструкции во втором блоке исходного кода Python (например, a = input ('Value of a')) были только текстом документации и не рассматривались как инструкции.
Lgen
@Lgen - Спасибо! Грамотное программирование nowebв функциях орг-режима удивительно и невероятно полезно! Пожалуйста, дайте мне знать, если вам нужны дополнительные примеры кода. Если вам нужно что-то, что не вписывается в формат вопросов и ответов, я буду рад опубликовать в моем репозитории GitHub.
Мелиорат
6

Я не думаю, что возможно получить действительно интерактивный ввод Python с помощью org-babel.

Вы можете использовать преамбулу, чтобы переопределить функцию ввода, чтобы она возвращала то, что вы хотите имитировать, используя ввод, например, здесь мы делаем так, чтобы пользователь выглядел как «3».

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

#+RESULTS:
: 3

В зависимости от того, что учащиеся видят, что экспортируется, они могут не увидеть, что вы сделали это.

Джон Китчин
источник
Спасибо Джону за предложенный ответ. Мне было интересно, если это можно расширить для множественного вызова функции ввода в блоке кода (например, a = input ("Value of") b = input ("Value of b")). Для создания texbook я обычно использую и «: export both» в выражении «# + BEGIN_SRC python», поэтому эта строка не должна быть видна в экспортированном тексте.
Lgen
Если вы используете сессию, это возможно: # + BEGIN_SRC python: сессия: экспорт не задан def input (x): если x == «Значение a»: вернуть 3 elif x == «Значение b»: вернуть 4 # + END_SRC # + РЕЗУЛЬТАТЫ: # + BEGIN_SRC python: вывод результатов: сессия a = input ('Value of a)) b = input (' Value of b ') print (a + b) # + END_SRC # + RESULTS::: >>> >>> 7
Джон Китчин
2

В качестве дополнения к решению Джона Китчина я предлагаю использовать генератор для предоставления последовательных значений, которые будут «питать» input(...)функции и strсистематически возвращать объект.

#+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
источник