- 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/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!