【问题标题】:Python-How to execute code and store into variable?Python-如何执行代码并存储到变量中?
【发布时间】:2020-03-27 20:32:22
【问题描述】:

所以我一直在为这个问题苦苦挣扎,现在似乎永远都是这样(我对 Python 还是很陌生)。 我正在使用 Python 3.7(由于我用于项目的软件包版本不同,需要它是 3.7)来开发一个人工智能聊天机器人系统,该系统可以根据您的文本输入与您交谈。程序在启动时会读取一系列 .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

Output on the website interface

基本上,需要它对“代码评估的结果:”输出说 HELLO。这应该让它到达聊天机器人在 Web 界面中用 HELLO 响应的位置,这是这里的最终目标。由于“要执行的代码是:”输出文本之后的 HELLO,它似乎正在执行代码。它只是没有像我需要的那样将它存储到一个变量中。

我尝试过 eval、exec、ast.literal_eval(),使用 str() 将输入转换为字符串,更改单引号和双引号,将 \ 放在引号对之前,以及其他几件事。每当我在程序执行代码时将其解释为“print(“HELLO”)”时,它都会抱怨语法。另外,从网上看了几天,我发现由于一堆问题,exec 和 eval 通常不受欢迎,但是我现在真的不在乎这一点,因为我正在尝试做一些在我之前有效的东西做一些好的并且有效的东西。我有一种感觉,这个问题像往常一样小而愚蠢,但我不知道它可能是什么。 :(

我使用这两个资源作为整个聊天机器人项目的基础:

Text Guide

Youtube Guide

另外,我很抱歉这个相当冗长和描述性的问题。我很少需要在 stackoverflow 上提出自己的问题,因为如果我有问题,它通常已经有了很好的答案。感觉就像我在这一点上已经尝试了一切。如果您对如何构建整个系统有更好的建议,或者您认为我应该尝试另一种方法,我愿意接受。

感谢您的任何/所有帮助。非常感谢! :)

【问题讨论】:

  • 嗨@Wowguy233 - 如果以下任何答案解决了您的问题,请单击复选标记考虑accepting one of them。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。

标签: python python-3.x chatbot execution evaluation


【解决方案1】:

问题在于 python 的 print() 没有返回值,这意味着它将始终返回 Noneeval 只计算某个表达式,然后返回该表达式的返回值。由于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 只能评估单个语句。如果你想将你的机器人扩展到多行语句,你需要使用exec,这会改变逻辑。这是一个很好的资源,详细说明了 evalexec 之间的区别:What's the difference between eval, exec, and compile?

【讨论】:

    【解决方案2】:

    很简单,只需转换尝试创建一个新列表并将该变量的更新值添加到其中,例如:

    如果你有一个变量名 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'
    

    这里所有的值都将存储在您的列表中,您也可以通过其他方式执行此操作,例如,如果您有多个值或答案,使用循环会更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-10
      • 1970-01-01
      • 1970-01-01
      • 2020-01-21
      • 2017-09-01
      相关资源
      最近更新 更多