OhY*_*Yee 6 python windows powershell python-3.x
此代码在Windows和Linux之间打印不同的字符串.
test.py:
print(";".join([str(i) for i in range(10000)]))
Run Code Online (Sandbox Code Playgroud)
平台:x86_64 Linux 4.4.0-17763 - Microsoft
Python版本:3.7.2
终端:bash,fish
缩写输出:
$ python --version
Python 3.7.2
$ python test.py
0;1;2;3;4;5;6....9997;9998;9999
$ python -u test.py
0;1;2;3;4;5;6....9997;9998;9999
Run Code Online (Sandbox Code Playgroud)
平台:Windows 10 1809
Python版本:3.6.8,3.7.0,3.7.2
终端:cmd,powershell
缩写输出:
./python --version
Python 3.6.8
./python test.py
0;1;2;3;4;5;6....9997;9998;9999
./python -u test.py
0;1;2;3;4;5;6....2663;2664;2665;26
Run Code Online (Sandbox Code Playgroud)
./python --version
Python 3.7.0
./python test.py
0;1;2;3;4;5;6....9997;9998;9999
./python -u test.py
0;1;2;3;4;5;6....2663;2664;2665;26
Run Code Online (Sandbox Code Playgroud)
./python --version
Python 3.7.2
./python test.py
0;1;2;3;4;5;6....9997;9998;9999
./python -u test.py
0;1;2;3;4;5;6....2663;2664;2665;26
Run Code Online (Sandbox Code Playgroud)
那么为什么在Windows中,-uarg会导致输出被截断(仅仅是0为了2666)?
(当使用python -u test.py > a.txt将输出重定向到文件时,它可以正常工作.)
也许有关于缓冲的事情?
通过 WINAPI 写入的控制台大小WriteFile有WriteConsoleW一个模糊定义的限制,如下所示:
nNumberOfCharsToWrite [in]
要写入的字符数。如果指定字符数的总大小超过可用堆,则该函数将失败并返回 ERROR_NOT_ENOUGH_MEMORY。
没有记录这指的是哪个“堆”。一个进程可以有多个不同大小的堆(固定或动态)。NT运行时库中的本机堆实现(例如RtlCreateHeap)可以在指定地址创建堆,这允许方便地访问与其他进程共享的内存。使用共享堆通常与本地进程间通信(LPC) 端口(或 NT 6.0+ 中的异步 LPC)结合使用。LPC 端口用于在应用程序和系统服务之间传递消息,例如会话管理器 (smss.exe)、服务控制管理器 (services.exe)、本地安全机构 (lsass.exe)、桌面会话服务器 (csrss.exe)和控制台主机 (conhost.exe) 的实例。直接排队到 LPC 端口的消息限制为 256 字节。通过将消息排队到引用共享内存的端口来传递较大的消息。
事实证明,控制台的旧实现(NT 6.3之前)使用LPC作为I/O通道,并且上述堆只有64 KiB。这是一个特殊的设计选择。我认为有人对用户模式子系统、消息传递酷爱喝得太多了。正确的 NT I/O 使用具有 I/O 系统服务的设备,包括NtCreateFile、NtReadFile、NtWriteFile和NtDeviceIoControlFile。
控制台应用程序不知道该堆中有多少可用于写入。Python 可以从 64 KiB 开始并逐渐减小,但其原始文件 I/O要求每次调用一个系统调用。相反,它将写入上限限制为 32 KiB,这应该会成功。此限制允许写入最多 16K UTF-16 代码点的宽字符字符串。一个复杂的问题是控制台 I/O 堆栈在 3.6+ 中使用 UTF-8,必须通过MultiByteToWideChar. 目前它只是重复地将 UTF-8 缓冲区分成两半,直到结果长度小于 16K。因此,在问题的示例中,写入 48,889 个字符会减半为 24,444 个字符,然后再次减半为 12,222 个字符。(IMO,最好尝试写入最多 16K 代码点;获取实际写入的数字,然后调用WideCharToMultiByte子字符串来确定写入的 UTF-8 字节数。当前的设计实际上存在一个错误,如果 UTF-8 2-4 字节序列与切点重叠。)
在 NT 6.3+ (Windows 8.1+) 中,控制台 I/O 没有此大小限制,因为它使用 ConDrv 设备和 I/O 系统调用而不是 LPC。-u然而,仅仅为了支持由命令行选项配置的无缓冲文本 I/O 堆栈而对代码进行特殊封装是不值得的。我们期望交互式控制台 I/O 能够被缓冲。实际上,普通调用不允许使用无缓冲文本 I/O open。例如:
>>> open('conout$', 'w', buffering=0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: can't have unbuffered text I/O
Run Code Online (Sandbox Code Playgroud)
对 Windows 7 的扩展支持将于 2020 年 1 月 14 日结束,因此 Python 3.8 将是支持它的最后一个版本。Python 3.9 中应删除控制台写入限制。