不同行为的原因是文件I/O操作的不同实现。
CPython implements 它是 fopen、fread 和 fwrite 之上的文件 I/O 函数,来自 stdio.h,并且正在处理 FILE * 流。
同时 PyPy implements 是 POSIX open、write 和 read 函数之上的文件 I/O,并且正在使用 int 文件描述符。
比较这两个 C 程序:
#include <stdio.h>
int main() {
FILE *a = fopen("file1", "a");
FILE *b = fopen("file1", "a");
fwrite("Test line 1\n", 12, 1, a);
fflush(a);
fwrite("Test line 2\n", 12, 1, b);
fflush(b);
fwrite("Test line 3\n", 12, 1, a);
fflush(a);
fwrite("Test line 4\n", 12, 1, b);
fclose(a);
fclose(b);
return 0;
}
和
#include <fcntl.h>
#include <unistd.h>
int main() {
int a = open("file1", O_CREAT | O_WRONLY | O_APPEND);
int b = open("file1", O_CREAT | O_WRONLY | O_APPEND);
write(a, "Test line 1\n", 12);
write(b, "Test line 2\n", 12);
write(a, "Test line 3\n", 12);
write(b, "Test line 4\n", 12);
close(a);
close(b);
return 0;
}
有关open 和fopen 之间区别的更多信息,您可以在question 的答案中找到。
更新:
在进一步检查 PyPy 代码库之后,在我看来,出于某种原因,doesn't use O_APPEND flag,但 O_WRONLY | O_CREAT 用于“a”模式。因此,正如 J.F. Sebastian 在 another answer 中提到的那样,在 PyPy 中,您需要在每次 write 调用后将 seek 放到文件末尾,这才是真正的原因。我想应该在 PyPy bugtracker 上创建一个错误,因为O_APPEND 标志在 Windows 和 Unix 上都可用。所以,PyPy 现在看起来像这样:
#include <fcntl.h>
#include <unistd.h>
int main() {
int a = open("file1", O_CREAT | O_WRONLY);
int b = open("file1", O_CREAT | O_WRONLY);
write(a, "Test line 1\n", 12);
write(b, "Test line 2\n", 12);
write(a, "Test line 3\n", 12);
write(b, "Test line 4\n", 12);
close(a);
close(b);
return 0;
}
如果没有 O_APPEND 标志,它应该重现 PyPy 行为。