我正在尝试制作一个程序,该程序将可执行文件名称作为参数,运行可执行文件并报告该运行的输入和输出。例如,考虑一个名为“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它允许用户与子程序交互,如上所示。它还需要 2 个可选参数:output_filter
and input_filter
。从文档中:
The 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
Enter radius of circle: 10
Area: 314.158997
[('output', 'Enter radius of circle: '), ('input', '1'), ('output', '1'), ('input', '0'), ('output', '0'), ('input', '\r'), ('output', '\r\n'), ('output', 'Area: 314.158997\r\n')]
正如您从输出中可以观察到的那样,输入是逐字符处理的,并且还作为输出回显,这造成了如此混乱。是否有可能改变这种行为,以便我的input_filter
仅当以下情况时才会运行Enter
被压?
或者更一般地说,实现我的目标的最佳方式是什么(有或没有pexpect
)?