Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用子流程有效地测试基于readline的Python程序?_Python_Unit Testing_Python 3.x_Subprocess_Readline - Fatal编程技术网

如何使用子流程有效地测试基于readline的Python程序?

如何使用子流程有效地测试基于readline的Python程序?,python,unit-testing,python-3.x,subprocess,readline,Python,Unit Testing,Python 3.x,Subprocess,Readline,我有一个Python程序,在某些情况下,它会提示用户输入文件名。但是,我想提供一个默认文件名,用户可以根据自己的意愿进行编辑。这通常意味着他们需要点击backspace键来删除当前文件名,并将其替换为他们喜欢的文件名 为此,我将Python 3改编为: def rlinput(prompt, prefill=''): readline.set_startup_hook(lambda: readline.insert_text(prefill)) try: retu

我有一个Python程序,在某些情况下,它会提示用户输入文件名。但是,我想提供一个默认文件名,用户可以根据自己的意愿进行编辑。这通常意味着他们需要点击backspace键来删除当前文件名,并将其替换为他们喜欢的文件名

为此,我将Python 3改编为:

def rlinput(prompt, prefill=''):
    readline.set_startup_hook(lambda: readline.insert_text(prefill))
    try:
        return input(prompt)
    finally:
        readline.set_startup_hook()

new_filename = rlinput("What filename do you want?", "foo.txt")
当程序按预期以交互方式运行时,此功能会正常工作-在退格并输入新文件名后,
new_filename
包含
bar.txt
或用户输入的任何文件名

但是,我还想使用单元测试来测试程序。一般来说,要做到这一点,我将程序作为子进程运行,以便将其输入提供给stdin(从而按照用户使用它的方式进行测试)。我有一些单元测试代码(简化)如下所示:

p = Popen(['mypythonutility', 'some', 'arguments'], stdin=PIPE)
p.communicate('\b\b\bbar.txt')
我的意图是,这应该模拟用户在提供的
foo.txt
上的“退格”,并输入
bar.txt

然而,这似乎没有达到预期的效果。相反,在一些调试之后,我的程序中的
新文件名
最终会与
\b\b\bbar.txt
等效。我期待的只是
bar.txt


我做错了什么?

从Python控制交互式子进程的适当方法是使用模块。此模块使子进程相信它正在交互终端会话中运行,并让父进程准确地确定哪些击键被发送到子进程

Pexpect是一个纯Python模块,用于生成子应用程序;控制它们;并对其输出中的预期模式做出响应。Pexpect的工作原理与Don Libes的Expect类似。Pexpect允许您的脚本生成一个子应用程序并控制它,就像人类键入命令一样


好的,谢谢。这很有意义(可以看到与Unix实用程序expect的相似之处)。我来看看。但是,您知道为什么子流程不能按我期望的方式工作吗?仍然对此感到困惑。@AndrewFerrier:可能是子进程中的readline库发现它正在从管道而不是交互式tty获取输入,并禁用了诸如
\b
处理之类的功能。是的,这听起来很有道理。我可以在我的实用程序中解决这个问题,但是很明显,我正在改变程序来处理测试——这不是一个好主意。将调查Pexpect。@AndrewFerrier:您可以使用
pty
模块在
子流程
模块上重新实现
Pexpect
模块的相应部分:在对Pexpect进行了大量的修改之后,我终于让它做了正确的事情。关键是使用
child.sendcontrol(“H”)
发送退格,这有点复杂。但这一切都是可行的。