【问题标题】:Redirecting Python Interpreter's IO重定向 Python 解释器的 IO
【发布时间】:2013-05-04 23:39:33
【问题描述】:

我编写了一个简单的调试器程序,它可以执行控制台程序并将其输出发送到“out”和“err”文件,并从“in”文件中检索其输入。现在,我想扩展它的功能来运行 Python 脚本。为此,我想我可以让调试器只运行 Python 解释器并将 Python 解释器与文件接口。

但是当我在调试器中运行 Python 解释器时,我看不到任何输出,就像使用普通程序一样。调试器有非常详细的错误日志,我在错误日志文件中看不到任何错误。

我使用了“ps -A”,但调试器似乎已经启动了 Python 解释器,原因有两个:1)进程 ID 相差 1 和 2)一旦我杀死 -9 python,调试器就会退出解释器(说明文件描述符已连接)。这是 ps -All 的输出:

1 R     0  1565     1 88  80   0 -  1040 -      pts/0    00:01:45 debugger
0 S     0  1566  1565  0  80   0 -  7782 pipe_w pts/0    00:00:00 python.out

并且调试器是这样启动的(python.out 是 python 解释器的副本):

debugger python.out

所以我想我的问题是,有人知道为什么这不起作用吗? Python 解释器对它的标准文件描述符做了什么奇怪的事情吗?

编辑:

  • 我还注意到 python.out 无法使用 python.out > out_file 重定向其 IO - 这可能与调试器遇到的问题有关,也可能无关。

  • 调试器不使用块缓冲。

  • 这是来自 /proc/pid/io 的一些 io 信息:

调试器(我将一些长度为 21 的数据写入“in”文件)

rchar: 21
wchar: 21
syscr: 300222462
syscw: 1
read_bytes: 0
write_bytes: 0
cancelled_write_bytes: 0

Python 解释器

rchar: 517268
wchar: 0
syscr: 93
syscw: 0
read_bytes: 0
write_bytes: 0
cancelled_write_bytes: 0

【问题讨论】:

  • 什么是“标准 .out 程序”,您如何“将其 IO 重定向到文件中”?输入肯定来自来自 .in 文件吗?还是您正在处理流,将其同时发送到.in 和 python 进程?
  • 一个标准的 .out 程序,在这种情况下,是一个使用 IO 的 std 文件描述符的程序。我将编辑我的问题以更准确地回答您的问题。
  • python.out 是 python 解释器。我将它从 user/bin 复制到我正在工作的目录中

标签: python linux stdio io-redirection


【解决方案1】:

Python 解释器的pipe_w 等待状态是一个赠品:它无法运行,因为它要么尝试从空管道读取,要么写入满管道。

在您的代码或解释器或两者中都使用了块缓冲,而您没有向我们展示足够多的内容来告诉我们。

为回应评论添加:

您认为您不是块缓冲,但 stdio 库可能在您不知情的情况下这样做。考虑简单:

main()
{
    puts("print ('hello, world!')\n");
    sleep(3600);
}

当您从终端运行它时,它会在终端上打印print ('hello, world!'),然后休眠一个小时,正如您所期望的那样。这是因为 stdio 库检测到 stdout 是一个终端,并在每个换行符上执行其缓冲区的 write()。这样做是因为人们喜欢在行缓冲输出准备好时看到它。但是,如果您将此程序的输出通过管道传输到python,则终端上一小时内不会显示任何内容;这是因为 stdio 库看到 stdout 是一个管道并切换到块缓冲模式。在块缓冲模式下,stdio 将等到它有 BUFSIZ 字符要写入并且在现代机器上 BUFSIZ 是 4096 或更高。

当你说“我可以确认调试器正在读取我传递给它的输入”时,由于 stdio 的这种模式切换,你在终端上测试你的调试器实际上并没有告诉你进程间通信是否是缓冲与否。 ps 的输出表明它正在缓冲。请参阅 setvbuf 了解如何控制缓冲。

或者您可以显示您的代码而不是无用的/proc/n/io。我的python 报告:

rchar: 288789
wchar: 0
syscr: 108
syscw: 0
read_bytes: 0
write_bytes: 0
cancelled_write_bytes: 0

但它仍然没有给出任何输出,并且直到时间到了才会给出,因为它的 /proc/n/wchan

pipe_wait

正如预期的那样。

【讨论】:

  • 我的代码没有使用块缓冲。我可以确认调试器正在读取我传递给它的输入。有没有办法可以确认口译员正在阅读该信息?或者,有没有办法检查解释器是否使用块缓冲?
  • @TaylorFlores 参见上面添加的内容。
  • 好的,我将不得不重写一些调试器,因为 setvbuf 仅适用于 FILE 结构(我使用整数)。感谢您的答复。即使我没有测试它,我也会认为它是一个答案,因为无论如何你似乎是对的。
猜你喜欢
  • 2012-12-08
  • 1970-01-01
  • 2012-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-06
相关资源
最近更新 更多