Python -Как выполнить код и сохранить в переменной? - PullRequest
1 голос
/ 27 марта 2020

Так что я боролся с этой проблемой сейчас, кажется, навсегда (я довольно новичок в Python). Я использую Python 3.7 (нужно, чтобы он был 3.7 из-за различий в версиях пакетов, которые я использую для проекта), чтобы разработать систему чат-бита AI, которая может общаться с вами на основе вашего ввода текста , Программа читает содержимое ряда файлов .yml при запуске. В одном из файлов .yml я разрабатываю синтаксис для случая, когда первые 5 символов соответствуют шаблону ^ ### ^, он вместо этого выполнит код и вернет результат этого выполнения, а не просто выведет текст обратно пользователю. Например:

Обычный разговор:

- - What is AI?

- Artificial Intelligence is the branch of engineering and science devoted to constructing machines that think.

Разговор на основе службы / кода:

- - Say hello to me

- ^###^print("HELLO")

Идея состоит в том, что когда вы просите его передать вам привет строка ^ ## ^ print ("HELLO") будет извлечена из файла .yml, первые 5 символов ответа будут удалены, ответ будет отправлен отдельной функции в коде python, где он запустит код и сохранит результат в переменной, которая будет возвращена из функции в переменную, которая выдаст хороший, чистый результат HELLO пользователю. Я понимаю, что это может быть немного сложным для понимания, но я исправлю свой код и сгущу все, как только исправлю всю эту ошибку. В качестве примечания: Oracle - это то, что я называю проектом. Я не пытаюсь впутать Java во весь этот беспорядок.

ПРОБЛЕМА заключается в том, что он не сохраняет результат запуска / исполнения / оценки кода в переменную, например это должно быть.

Мой код:

def executecode(input):
    print("The code to be executed is: ",input)
        #note: the input may occasionally have single quotes and/or double quotes in the input string
    result = eval("{}".format(input))
    print ("The result of the code eval: ", result)
    test = eval("2+2")
    test
    print(test)
    return result


@app.route("/get")
def get_bot_response():
    userText = request.args.get('msg')
    print("Oracle INTERPRETED input: ", userText)
    ChatbotResponse = str(english_bot.get_response(userText))
    print("CHATBOT RESPONSE VARIABLE: ", ChatbotResponse)
    #The interpreted string was a request due to the ^###^ pattern in front of the response in the custom .yml file
    if ChatbotResponse[:5] == '^###^':
        print("---SERVICE REQUEST---")
        print(executecode(ChatbotResponse[5:]))
        interpreter_response = executecode(ChatbotResponse[5:])
        print("Oracle RESPONDED with: ", interpreter_response)
    else:
        print("Oracle RESPONDED with: ", ChatbotResponse)
    return ChatbotResponse

Когда я запускаю этот код, это вывод:

Oracle INTERPRETED input:  How much RAM do you have?
CHATBOT RESPONSE VARIABLE:  ^###^print("HELLO")
---SERVICE REQUEST---
The code to be executed is:  print("HELLO")
HELLO
The result of the code eval:  None
4
None
The code to be executed is:  print("HELLO")
HELLO
The result of the code eval:  None
4
Oracle RESPONDED with:  None

Вывод на интерфейс веб-сайта

По сути, нужно сказать HELLO для вывода «Результат кода eval:». Это должно привести к тому, что чат-бот отвечает HELLO в веб-интерфейсе, что является конечной целью здесь. Кажется, что он выполняет код из-за HELLO после «Код, который должен быть выполнен:», текст вывода. Он просто не хранится в переменной, как мне нужно.

Я пытался eval, exe c, ast.literal_eval (), преобразовывая ввод в строку с помощью str (), изменяя одинарные и двойные кавычки, помещая \ перед парами цитаты и несколько других вещей. Всякий раз, когда я получаю его там, где программа интерпретирует «print (« HELLO »)» при выполнении кода, она жалуется на синтаксис. Кроме того, за несколько дней поиска в Интернете я понял, что exe c и eval, как правило, не пользуются популярностью из-за множества проблем, однако в настоящий момент меня это не волнует, потому что я пытаюсь сделать что-то, что работает, прежде чем я сделаю что-то хорошее и работает. У меня такое чувство, что проблема в чем-то маленьком и глупом, как всегда, но я понятия не имею, что это может быть. : (

Я использовал эти 2 ресурса в качестве основы для всего проекта чата:

Текстовое руководство

Руководство Youtube

Кроме того, я прошу прощения за довольно длинный и описательный вопрос. Редко, когда я задаю свой вопрос на stackoverflow, потому что если у меня есть вопрос, он обычно уже имеет хороший ответ. как будто я все перепробовал на этом этапе. Если у вас есть лучшее предложение о том, как сделать всю эту систему, или вы думаете, что я должен попытаться подойти к этому по-другому, я открыт для идей.

Спасибо за любую помощь. Очень ценим! :)

Ответы [ 2 ]

0 голосов
/ 28 марта 2020

Легко просто преобразовать, попытаться создать новый список и добавить в него обновленные значения этой переменной, например:

, если у вас есть имя переменной myVar, храните значения или даже вопросы неважно.

1- Сначала объявите новый список в вашем коде, как показано ниже:

myList = []

2- Если вам нужно ответить или отобразить значение через myVar, то вы можете сделать как показано ниже:

myList.append(myVar)

и это, если вместо этого у вас есть генератор значений, если вам нужно обратное, что означает, что значения уже сохранены, тогда вы просто обновите второй шаг, чтобы он был похож на следующий:

myList[0]='The first answer of the first question'
myList[1]='The second answer of the second question'

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

0 голосов
/ 28 марта 2020

Проблема в том, что python print() не имеет возвращаемого значения, то есть оно всегда будет возвращать None. eval просто вычисляет некоторое выражение и возвращает возвращаемое значение из этого выражения. Так как print() возвращает None, eval некоторого оператора печати также вернет None.

>>> from_print = print('Hello')
Hello
>>> from_eval = eval("print('Hello')")
Hello
>>> from_print is from_eval is None
True

Что вам нужно, это менеджер потоков io! Вот возможное решение, которое захватывает любой вывод io и возвращает, что если выражение оценивается как None.

from contextlib import redirect_stout, redirect_stderr
from io import StringIO

# NOTE: I use the arg name `code` since `input` is a python builtin
def executecodehelper(code):
    # Capture all potential output from the code
    stdout_io = StringIO()
    stderr_io = StringIO()

    with redirect_stdout(stdout_io), redirect_stderr(stderr_io):
        # If `code` is already a string, this should work just fine without the need for formatting.
        result = eval(code)

    return result, stdout_io.getvalue(), stderr_io.getvalue()

def executecode(code):
    result, std_out, std_err = executecodehelper(code)

    if result is None:
        # This code didn't return anything. Maybe it printed something?
        if std_out:
            return std_out.rstrip() # Deal with trailing whitespace
        elif std_err:
            return std_err.rstrip()
        else:
            # Nothing was printed AND the return value is None!
            return None
    else:
        return result

В качестве последнего примечания, этот подход тесно связан с eval, поскольку eval может оценивать только одно утверждение. Если вы хотите расширить свой бот до многострочных операторов, вам нужно будет использовать exe c, который изменит лог c. Вот большой ресурс, подробно описывающий различия между eval и exec: В чем разница между eval, exe c и compile?

...