gpt4 book ai didi

python - 对 C 和 Python 中的缓冲和无缓冲 stdout/stderr 感到困惑

转载 作者:行者123 更新时间:2023-12-02 02:04:25 26 4
gpt4 key购买 nike

当涉及到 stdoutstderr 被缓冲/未缓冲的问题时,我对一些事情感到困惑:

1)

语句“stdout/err is buffered/unbuffered”是由我的操作系统编程语言库函数(特别是write()<我正在使用的/code> 或 print() 函数)?

在使用 C 语言编程时,我始终遵循以下规则:stdout 是有缓冲的,而 stderr 是无缓冲的。我通过在 while 循环中的 putchar() 语句之后调用 sleep() 来查看放置在 sleep() 上的各个字符,从而看到了这一点。 code>stderr 是一一对应的,而 stdout 中只出现了完整的行。当我尝试在 python 中复制这个程序时,stderrstdout 都有相同的行为:生成完整的行 - 所以我查了一下并发现 a post也就是说:

sys.stderr is line-buffered by default since Python 3.9.

因此问题 - 因为我的印象是 stderr 的缓冲/非缓冲行为是由操作系统决定和修复的,但显然,代码库可以自由地实现自己的行为?我可以假设编写一个在没有缓冲区的情况下写入标准输出的例程吗?

相关代码片段供引用:

/* C */
while ((c = fgetc(file)) != EOF) {
fputc(c, stdout /* or stderr */);
usleep(800);
}

# Python
for line in file:
for ch in line:
print(ch, end='', file=sys.stdout) # or sys.stderr
time.sleep(0.08);

2)

其次,我对缓冲需求的理解是:由于磁盘访问比RAM访问慢,写入单个字节效率低下,因此字节被写入 block 中。但是写入设备文件(例如 /dev/stdout/dev/stdin)与写入磁盘相同吗? (磁盘不是应该是永久的吗?写入 stdoutstderr 的内容仅出现在终端中(如果已连接,然后丢失,对吗?)

3)

最后,如果效率较低,是否真的需要在 C 中对 stderr 进行无缓冲?

最佳答案

Is the statement "stdout/err is buffered/unbuffered" decided by my Operating System or the programming language library functions (particular the write() or print() functions) that I am working with ?

主要是由编程语言的实现决定的,编程语言对此进行了标准化。例如,C语言规范说:

At program startup, three text streams are predefined and need not beopened explicitly — standard input (for reading conventional input),standard output (for writing conventional output), and standard error (for writing diagnostic output). As initially opened, thestandard error stream is not fully buffered; the standard input andstandard output streams are fully buffered if and only if the streamcan be determined not to refer to an interactive device.

(C2017,第 7.21.3/7 段)

同样,sys.stdinsys.stdoutsys.stderr 的 Python 文档说:

When interactive, the stdout stream is line-buffered. Otherwise, it isblock-buffered like regular text files. The stderr stream isline-buffered in both cases. You can make both streams unbuffered bypassing the -u command-line option or setting the PYTHONUNBUFFEREDenvironment variable.

但是请注意,这两种特定语言都提供了更改标准流缓冲的机制(或者在 Python 情况下,至少是 stdoutstderr )。

此外,仅当您使用流(C)或文件对象(Python)时,上述内容才相关。在 C 中,这是所有 stdio 函数所使用的——printf()fgets()fwrite()等等。 -- 但这不是POSIX原始I/O函数,例如read()write() 使用。如果您使用原始 I/O 接口(interface)(例如后者),那么只有您手动执行的任何缓冲。

Hence the question - because I was under the impression that the behaviour of stderr being buffered/unbuffered was decided and fixed by the OS

没有。操作系统(至少Unix(包括Mac)和Windows)不代表程序执行I/O缓冲。在某些情况下,编程语言实现确实如此,然后它们就可以控制细节。

but apparently, code libraries free to implement their own behaviour ?

比这更微妙一些,但基本上是的。

Can I hypothetically write a routine that writes to stdout without a buffer ?

也许吧。至少在 C 或 Python 中,您可以对 stdout 流的缓冲模式进行一些控制。在C中你可以在运行时动态调整它,但在Python中我认为缓冲模式是在Python启动时决定的。

您还可以通过在底层文件描述符上执行(原始)I/O 来绕过缓冲流的缓冲区,但这是一种非常糟糕的形式,并且根据详细信息,它可能会产生未定义的行为。

Secondly, my understanding of the need for buffering is that: since disk access is slower than RAM access, writing individual bytes would be inefficient and thus bytes are written in blocks.

所有 I/O 都很慢,甚至是终端的 I/O。磁盘 I/O 往往特别慢,但缓冲所有设备的 I/O 通常会提高程序性能。

But is writing to a device file like /dev/stdout and /dev/stdin the same as writing to disk?

有时它完全写入磁盘(查找 I/O 重定向)。不同的设备确实具有不同的性能特征,因此缓冲可能比其他设备更能提高某些设备的性能,但同样,所有 I/O 都很慢。

Finally, is there really a need for stderr to be unbuffered in C if it is less efficient?

在 C 中,stderr 不被缓冲(默认情况下)的目的是使定向到那里的消息尽快写入底层设备(通常是终端)。对于该政策最想传达的信息类型来说,效率并不是真正需要考虑的问题。

关于python - 对 C 和 Python 中的缓冲和无缓冲 stdout/stderr 感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68640497/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com