【问题标题】:python stdout.flush() does NOT flush last white characters like '\n'python stdout.flush() 不会刷新最后一个白色字符,如 '\n'
【发布时间】:2013-05-12 13:28:55
【问题描述】:

我有两个程序。第一个 (subprocess.cpp) 用 C++ 编写:

#include <stdio.h>

int main() {

    char * line = new char[1000];

    // first scan
    scanf("%s\n", line);
    printf("%s\n", line);
    fflush(stdout);

    // second scan
    scanf("%s\n", line);
    printf("%s\n", line);
    fflush(stdout);

    return 0;
}

这个程序只是从标准输入中获取两个字符串并在标准输出上打印,毕竟是刷新。 这是用 Python 2.7 编写的第二个程序 (test.py):

from subprocess import Popen
from subprocess import PIPE
from subprocess import Popen

# create process
my_process = Popen("./subprocess", stdin = PIPE, stdout = PIPE)

# send initial data
my_process.stdin.write('abc\n')
my_process.stdin.flush()
my_process.stdin.write('xyz\n')
my_process.stdin.flush()

# read data from subprocess
print "Subprocess line 1 :: " + str(my_process.stdout.readline())
print "Subprocess line 2 :: " + str(my_process.stdout.readline())

这个脚本应该启动子进程,发送和检索两个字符串。看看发生了什么:

marcin@marcin-Aspire-7540 ~/Desktop/inzynierka $ g++ subprocess.cpp -o subprocess
marcin@marcin-Aspire-7540 ~/Desktop/inzynierka $ python test.py 
Subprocess line 1 :: abc

test.py 正在等待程序 subprocess 的第二行。程序 subprocess 无法发送第二个字符串,因为它正在等待 '\n' 字符。

如果我将subprocess.cpp 中的第二个scanf 更改为scanf("%s\n", line);(没有\n),一切正常。当我在test.py 中再发送一行时也会发生同样的情况:

# send initial data
my_process.stdin.write('abc\n')
my_process.stdin.flush()
my_process.stdin.write('xyz\n')
my_process.stdin.flush()
my_process.stdin.write('ADDITIONAL\n')
my_process.stdin.flush()

似乎 Python 不会在刷新后发送最后一个 \n 字符(参见更改 scanf 的示例)。在test.py 中添加一个额外的写入和刷新证明,在刷新后丢失的 \n 字符仍在缓冲区中。

怎么办?如何让 Python 的 flush 刷新所有字符?

【问题讨论】:

    标签: python stdout stdin flush


    【解决方案1】:

    错误是带有 \n i 格式字符串的 scanf 行为。它接缝 scanf("%s\n") 将在使用管道时在 \n 之后的第一个非空白字符之后或在使用终端时在第一个非空行之后返回(因为第一个非空白字符将在下一个 \n 之后被刷新)。

    关键是您可能不是有意使用 scanf("%s\n")。我猜你真正想要的是:

    scanf("%s%*[^\n]", line);
    

    它将读取单词,然后丢弃同一行中的所有字符。

    【讨论】:

    • 同意,问题是在 scanf 格式字符串中使用了 '\n',而不是在 Python 中。实际上,只需 scanf("%s", line) 就可以正常工作,甚至 gets(line)(取决于意图)。
    • 谢谢,我不知道问题不在于 Python 本身。
    【解决方案2】:

    问题在于scanf("%s\n", line),第二个scanf() 需要读取另一行才能找到非空白字符。

    类似案例here有很好的解释。

    我还用strace 进行了检查,Python 发送了最后一个'\n' 字符。

    pid 6611: test.py
    pid 6613: subprocess
    
    > strace -f python test.py
    [pid  6611] write(4, "abc\n", 4 <unfinished ...>
    ...
    [pid  6611] write(4, "abc\n", 4 <unfinished ...>
    ...
    [pid  6613] read(0, "abc\nxyz\n", 4096) = 8
    ...
    [pid  6613] write(1, "abc\n", 4)        = 4
    [pid  6611] <... read resumed> "a", 1)  = 1
    [pid  6613] read(0,  <unfinished ...>
    [pid  6611] read(5, "b", 1)             = 1
    [pid  6611] read(5, "c", 1)             = 1
    [pid  6611] read(5, "\n", 1)            = 1
    ...
    [pid  6611] write(1, "Subprocess line 1 :: abc\n", 25Subprocess line 1 :: abc) = 25
    [pid  6611] write(1, "\n", 1)           = 1
    [pid  6611] read(5, 
    

    【讨论】:

      猜你喜欢
      • 2021-02-11
      • 2013-03-31
      • 2018-08-19
      • 2021-09-13
      • 2017-12-25
      • 2014-10-05
      • 2015-12-09
      • 2018-12-03
      • 2019-03-20
      相关资源
      最近更新 更多