我正在尝试编写一个程序,该程序以可执行文件名作为参数,运行可执行文件并报告该运行的输入和输出。例如,考虑一个名为“circle”的子程序。我的程序应如下所示:
$ python3 capture_io.py ./circle Enter radius of circle: 10 Area: 314.158997 [('output', 'Enter radius of circle: '), ('input', '10\n'), ('output', 'Area: 314.158997\n')]
我决定使用pexpect
模块完成此任务。它有一个名为interact
的方法,允许用户与子程序进行交互,就像上面看到的那样。它还有两个可选参数:output_filter
和input_filter
。从文档中可以得知:
output_filter
将接收子进程的所有输出。input_filter
将接收用户的所有键盘输入。
所以这是我编写的代码:
capture_io.py
import sys
import pexpect
_stdios = []
def read(data):
_stdios.append(("output", data.decode("utf8")))
return data
def write(data):
_stdios.append(("input", data.decode("utf8")))
return data
def capture_io(argv):
_stdios.clear()
child = pexpect.spawn(argv)
child.interact(input_filter=write, output_filter=read)
child.wait()
return _stdios
if __name__ == '__main__':
stdios_of_child = capture_io(sys.argv[1:])
print(stdios_of_child)
circle.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
float radius, area;
printf("Enter radius of circle: ");
scanf("%f", &radius);
if (radius < 0) {
fprintf(stderr, "Negative radius values are not allowed.\n");
exit(1);
}
area = 3.14159 * radius * radius;
printf("Area: %f\n", area);
return 0;
}
以下是输出结果:
$ python3 capture_io.py ./circle 输入圆的半径: 10 面积: 314.158997 [('output', '输入圆的半径: '), ('input', '1'), ('output', '1'), ('input', '0'), ('output', '0'), ('input', '\r'), ('output', '\r\n'), ('output', '面积: 314.158997\r\n')]
从输出结果可以看出,输入字符逐个处理,并作为输出回显,这会导致混乱。有没有可能更改此行为,使得只有在按下“Enter”键时才运行 input_filter
?
或者更一般地说,无论是否使用 pexpect
,实现我的目标的最佳方法是什么?
script
(检查--log-in
和--log-out
选项)和tee
。 - VPfB--log-in
和--log-out
选项。(来自 util-linux 2.31.1 的脚本) - Asocia--log-in
,您是正确的,它是最近在2.35中添加的。 - VPfBbash
编程不熟悉,不确定该如何实现。最终,唯一的要求是简单。如果安装tee
命令可以以自然的方式解决问题,那么这可能不是什么大问题。当我输入man tee
时,它说将标准输入复制到每个文件,并同时复制到标准输出中。
所以看起来好像它分离了输入和输出。是否有可能在保留顺序的情况下(即哪个输入在哪个输出之后,反之亦然),将这两者结合起来呢? - Asocia