【问题标题】:Interactive callback is not longer called on user input用户输入不再调用交互式回调
【发布时间】:2021-12-19 17:15:34
【问题描述】:

我正在尝试使用sh python 库制作一个交互式示例。

借鉴interactive-callbacks documentation的想法,我写了两个简单的脚本。

# test_example1.py
import sh

def interact(line, stdin):
    if "Hello" in line:
        stdin.put("me\n")
        return True # end
    print(f">> line: {line}")


print("-Start-")
response = sh.example1(_out=interact, _bg=True)
response.wait()
print("-End-")

shell 脚本如下所示:

#!/bin/bash
# example1
echo Good Morning, sir.
echo -n Hello, who am I talking to?:
read varname
echo It\'s nice to meet you $varname

但在控制台中程序不会继续读取更多行

-Start-
>> line: Good Morning, sir.
(no more chars, so the input is never shown)

挖掘代码,投票选择器似乎永远不会被echo -n Hello, who am I talking to?:唤醒

删除 `-n' 标志,让写入 '\n' 可以解决问题,但情况并非如此,因为某些脚本会提示并在同一行中等待响应。

我尝试使用不同的标志组合,但没有任何积极的结果。 sh 库看起来棒极了,所以我确定我错过了。

谁能帮我写一些互动的例子?

【问题讨论】:

  • sh 标签用于 Bourne shell 本身,而不是同名的 Python 库。
  • 我猜echo -n 正在离开图书馆;它可能正在使用缓冲 I/O,因此在它看到换行符(或大量输出迫使缓冲区被刷新)之前什么都不会发生。
  • The documentation 建议将 _out_bufsize 设置为 0 以禁用缓冲。
  • 谢谢@tripleee response = sh.example1(_out=interact, _bg=False, _out_bufsize=0) 让我调用每个字符,让我有机会编写整行并稍后应用一些正则表达式。
  • 随意张贴作为答案并(最终)接受它。接受答案通过将您的问题标记为已解决来帮助未来的访问者。另见help.

标签: python interactive


【解决方案1】:

了解管道的基本方法:

import sh
def interact(**rules):
    buffer = ''
    def process(chunk, stdin, process):
        nonlocal buffer
        buffer += chunk
        for regexp, answer in rules.items():
            if re.search(regexp, buffer):
                stdin.put(answer + '\n')
                buffer=''
    return process

sh.example1(_out=interact(talking='me'), _out_bufsize=0)

可以与 python input 或 bash read 等不发送以 \n 结尾的行的提示交互。

最终使用更紧凑的调用方式:

import sh

def reply(**kwargs):
    kw = dict(_out_bufsize=0)
    rules = {}
    for k, v in kwargs.items():
        if k[0] == '_':
            kw[k] = v
        else:
            rules[k] = v
        kw['_out'] = interact(**rules)
    return kw


def interact(**rules):
    buffer = ''
    def process(chunk, stdin, process):
        nonlocal buffer
        buffer += chunk
        for regexp, answer in rules.items():
            if re.search(regexp, buffer):
                stdin.put(answer + '\n')
                buffer=''

    return process

sh.example1(**reply(talking='me'))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 2011-10-09
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多