- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想实现与 this 非常相似的东西.
我的实际目标是在 python 中运行 Rasa。摘自 Rasa 的网站:
Rasa is a framework for building conversational software: Messenger/Slack bots, Alexa skills, etc. We’ll abbreviate this as a bot in this documentation.
它基本上是一个在命令提示符下运行的聊天机器人。这是它在 cmd 上的工作方式:
现在我想从 python 运行 Rasa,以便我可以将它与基于 Django 的网站集成。即我想继续从用户那里获取输入,将其传递给 rasa,rasa 处理文本并给我一个输出,我将其显示给用户。
我已经试过了(现在从 cmd 运行它)
import sys
import subprocess
from threading import Thread
from queue import Queue, Empty # python 3.x
def enqueue_output(out, queue):
for line in iter(out.readline, b''):
queue.put(line)
out.close()
def getOutput(outQueue):
outStr = ''
try:
while True: #Adds output from the Queue until it is empty
outStr+=outQueue.get_nowait()
except Empty:
return outStr
p = subprocess.Popen('command_to_run_rasa',
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=False,
universal_newlines=True,
)
outQueue = Queue()
outThread = Thread(target=enqueue_output, args=(p.stdout, outQueue))
outThread.daemon = True
outThread.start()
someInput = ""
while someInput != "stop":
someInput = input("Input: ") # to take input from user
p.stdin.write(someInput) # passing input to be processed by the rasa command
p.stdin.flush()
output = getOutput(outQueue)
print("Output: " + output + "\n")
p.stdout.flush()
但它只适用于第一行输出。不适用于连续的输入/输出周期。请参阅下面的输出。
如何让它在多个周期内工作?我提到了 this ,我想我从中理解了我的代码中的问题,但我不知道如何解决它。
编辑:我在 Windows 10 上使用 Python 3.6.2(64 位)
最佳答案
您需要继续与您的子进程进行交互 - 目前,一旦您从子进程中选择了输出,您就可以关闭它的 STDOUT
流。
下面是继续用户输入-> 处理输出循环的最基本的方法:
import subprocess
import sys
import time
if __name__ == "__main__": # a guard from unintended usage
input_buffer = sys.stdin # a buffer to get the user input from
output_buffer = sys.stdout # a buffer to write rasa's output to
proc = subprocess.Popen(["path/to/rasa", "arg1", "arg2", "etc."], # start the process
stdin=subprocess.PIPE, # pipe its STDIN so we can write to it
stdout=output_buffer, # pipe directly to the output_buffer
universal_newlines=True)
while True: # run a main loop
time.sleep(0.5) # give some time for `rasa` to forward its STDOUT
print("Input: ", end="", file=output_buffer, flush=True) # print the input prompt
print(input_buffer.readline(), file=proc.stdin, flush=True) # forward the user input
您可以将 input_buffer
替换为来自您的远程用户的缓冲区,并将 output_buffer
替换为将数据转发给您的用户的缓冲区,然后您您基本上会得到您正在寻找的东西 - 子流程将直接从用户那里获取输入 (input_buffer
) 并将其输出打印给用户 (output_buffer
) .
如果您需要在所有这些都在后台运行时执行其他任务,只需在单独的线程中运行 if __name__ == "__main__":
守卫下的所有内容,我建议添加一个 try..except
block 以获取 KeyboardInterrupt
并正常退出。
但是......很快你就会注意到它并不是一直都能正常工作 - 如果等待 rasa
打印它的 的时间超过半秒STDOUT
并进入等待STDIN
阶段,输出将开始混合。这个问题比您想象的要复杂得多。主要问题是 STDOUT
和 STDIN
(和 STDERR
)是独立的缓冲区,您无法知道子进程何时真正期待其 标准输入
。这意味着如果没有来自子进程的明确指示(例如,您在 Windows CMD 提示符的 STDOUT
中有 \r\n[path]>
),您只能将数据发送到子进程 STDIN
并希望它被拾取。
根据您的屏幕截图,它并没有真正给出可区分的 STDIN
请求提示,因为第一个提示是 ... :\n
然后等待 STDIN
,但是一旦命令被发送,它就会列出选项,而不指示其结束 STDOUT
流(技术上使提示只是 ...\n
但这也将匹配它前面的任何行)。也许你可以聪明地逐行阅读 STDOUT
,然后在每一行上测量自子进程写入以来已经过去了多少时间,一旦达到不活动阈值,假设 rasa
需要输入并提示用户输入。像这样的东西:
import subprocess
import sys
import threading
# we'll be using a separate thread and a timed event to request the user input
def timed_user_input(timer, wait, buffer_in, buffer_out, buffer_target):
while True: # user input loop
timer.wait(wait) # wait for the specified time...
if not timer.is_set(): # if the timer was not stopped/restarted...
print("Input: ", end="", file=buffer_out, flush=True) # print the input prompt
print(buffer_in.readline(), file=buffer_target, flush=True) # forward the input
timer.clear() # reset the 'timer' event
if __name__ == "__main__": # a guard from unintended usage
input_buffer = sys.stdin # a buffer to get the user input from
output_buffer = sys.stdout # a buffer to write rasa's output to
proc = subprocess.Popen(["path/to/rasa", "arg1", "arg2", "etc."], # start the process
stdin=subprocess.PIPE, # pipe its STDIN so we can write to it
stdout=subprocess.PIPE, # pipe its STDIN so we can process it
universal_newlines=True)
# lets build a timer which will fire off if we don't reset it
timer = threading.Event() # a simple Event timer
input_thread = threading.Thread(target=timed_user_input,
args=(timer, # pass the timer
1.0, # prompt after one second
input_buffer, output_buffer, proc.stdin))
input_thread.daemon = True # no need to keep the input thread blocking...
input_thread.start() # start the timer thread
# now we'll read the `rasa` STDOUT line by line, forward it to output_buffer and reset
# the timer each time a new line is encountered
for line in proc.stdout:
output_buffer.write(line) # forward the STDOUT line
output_buffer.flush() # flush the output buffer
timer.set() # reset the timer
您可以使用类似的技术来检查更复杂的“预期用户输入”模式。有一个完整的模块叫做 pexpect
专为处理此类任务而设计,如果您愿意放弃一些灵 active ,我衷心推荐它。
现在...综上所述,您知道Rasa
是用 Python 构建的,作为 Python 模块安装并具有 Python API,对吧?既然您已经在使用 Python,那么当您可以直接从 Python 代码运行它时,为什么还要将其称为子进程并处理所有这些 STDOUT/STDIN
恶作剧?只需导入它并直接与之交互,他们甚至有一个非常简单的示例可以完全满足您的要求:Rasa Core with minimal Python .
关于python - 从 python 中运行交互式程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50434204/
好的,所以我想从批处理文件运行我的整个工作环境... 我想要实现什么...... 打开新的 powershell,打开我的 API 文件夹并从该文件夹运行 VS Code 编辑器(cd c:\xy;
我正在查看 Cocoa Controls 上的示例并下载了一些演示。我遇到的问题是一些例子,比如 BCTabBarController ,不会在我的设备上构建或启动。当我打开项目时,它看起来很正常,没
我刚刚开始学习 C 语言(擅长 Java 和 Python)。 当编写 C 程序(例如 hello world)时,我在 ubuntu cmd 行上使用 gcc hello.c -o hello 编译
我在 php 脚本从 cron 开始运行到超时后注意到了这个问题,但是当它从命令行手动运行时这不是问题。 (对于 CLI,PHP 默认的 max_execution_time 是 0) 所以我尝试运行
我可以使用命令行运行测试 > ./node_modules/.bin/wdio wdio.conf.js 但是如果我尝试从 IntelliJ 的运行/调试配置运行它,我会遇到各种不同的错误。 Fea
Error occurred during initialization of VM. Could not reserve enough space for object heap. Error: C
将 Anaconda 安装到 C:\ 后,我无法打开 jupyter 笔记本。无论是在带有 jupyter notebook 的 Anaconda Prompt 中还是在导航器中。我就是无法让它工作。
我遇到一个问题,如果我双击我的脚本 (.py),或者使用 IDLE 打开它,它将正确编译并运行。但是,如果我尝试在 Windows 命令行中运行脚本,请使用 C:\> "C:\Software_Dev
情况 我正在使用 mysql 数据库。查询从 phpmyadmin 和 postman 运行 但是当我从 android 发送请求时(它返回零行) 我已经记录了从 android 发送的电子邮件是正确
所以这个有点奇怪 - 为什么从 Java 运行 .exe 文件会给出不同的输出而不是直接运行 .exe。 当 java 在下面的行执行时,它会调用我构建的可与 3CX 电话系统配合使用的 .exe 文
这行代码 Environment.Is64BitProcess 当我的应用单独运行时评估为真。 但是当它在我的 Visual Studio 单元测试中运行时,相同的表达式的计算结果为 false。 我
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
我写了一个使用 libpq 连接到 PostgreSQL 数据库的演示。 我尝试通过包含将 C 文件连接到 PostgreSQL #include 在我将路径添加到系统变量 I:\Program F
如何从 Jenkins 运行 Android 模拟器来运行我的测试?当我在 Execiute Windows bath 命令中写入时,运行模拟器的命令: emulator -avd Tester 然后
我已经配置好东西,这样我就可以使用 ssl 登录和访问在 nginx 上运行的 errbit 我的问题是我不知道如何设置我的 Rails 应用程序的 errbit.rb 以便我可以运行测试 nginx
我编写了 flutter 应用程序,我通过 xcode 打开了 ios 部分并且应用程序正在运行,但是当我通过 flutter build ios 通过 vscode 运行应用程序时,我得到了这个错误
我有一个简短的 python 脚本,它使用日志记录模块和 configparser 模块。我在Win7下使用PyCharm 2.7.1和Python 3.3。 当我使用 PyCharm 运行我的脚本时
我在这里遇到了一些难题。 我的开发箱是 64 位的,windows 7。我所有的项目都编译为“任何 CPU”。该项目引用了 64 位版本的第 3 方软件 当我运行不使用任何 Web 引用的单元测试时,
当我注意到以下问题时,我正在做一些 C++ 练习。给定的代码将不会在 Visual Studio 2013 或 Qt Creator 5.4.1 中运行/编译 报错: invalid types 'd
假设我有一个 easteregg.py 文件: from airflow import DAG from dateutil import parser from datetime import tim
我是一名优秀的程序员,十分优秀!