gpt4 book ai didi

Windows "Handle Invalid"上的 Python 将标准输出重定向到文件时

转载 作者:可可西里 更新时间:2023-11-01 10:12:42 25 4
gpt4 key购买 nike

我试图修复的脚本使用以下范例将标准输出重定向到文件。

import os
stdio_file = 'temp.out'
flag = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
stdio_fp = os.open(stdio_file, flag)
os.dup2(stdio_fp, 1)
print("hello")

在 Python 2 上,这有效。在 Python 3 上,你会得到一个 OSError

Traceback (most recent call last):
File "test.py", line 6, in <module>
print("hello")
OSError: [WinError 6] The handle is invalid
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
OSError: [WinError 6] The handle is invalid

我假设有更可取的方法通过文件路由标准输出,但我想知道为什么这种方法在 Python 3 中停止工作,是否有一种简单的方法来修复它?

最佳答案

诸如 os.dup2(stdio_fp, 1) 之类的代码将在 Python 3.5 及更早版本中运行,或者在定义了环境变量 PYTHONLEGACYWINDOWSSTDIO 的 3.6+ 中运行。

问题是 print 写入了仅用于控制台 I/O 的 sys.stdout 对象。具体来说,在 3.6+ 中,Python 3 标准输出文件的原始层(即 sys.stdout.buffer.raw)是一个 io._WindowsConsoleIO 实例,而 stdout 最初是一个控制台文件1。此对象缓存标准输出文件描述符2 的初始句柄值。随后,dup2 关闭此句柄,同时将文件描述符与“temp.out”的重复句柄重新关联。此时缓存的句柄不再有效。 (实际上,它不应该缓存句柄,因为与控制台 I/O 的成本相比,调用 _get_osfhandle 相对便宜。)但是,即使它具有“temp.out”的有效句柄",sys.stdout.write 无论如何都会失败,因为 _WindowsConsoleIO 使用仅限控制台的函数 WriteConsoleW 而不是通用的 WriteFile.

您需要重新分配 sys.stdout,而不是使用 dup2 等低级操作绕过 Python 的 I/O 堆栈。我知道从 Unix 开发人员的角度来看这并不理想。我希望我们可以重新实现 Windows 控制台支持 Unicode 的方式,而不引入这个仅限控制台的 _WindowsConsoleIO 类,它会破坏人们几十年来一直依赖的低级模式。


1。添加了 _WindowsConsoleIO 以支持 Windows 控制台中的所有 Unicode(至少控制台可以支持它)。为此,它使用控制台的 UTF-16 宽字符 API(例如 ReadConsoleWWriteConsoleW)。以前,CPython 的控制台支持仅限于使用基于字节的通用 I/O(例如 ReadFileWriteFile)使用 Windows 代码页编码的文本。

2。 Windows 使用句柄来引用内核对象,例如 File 对象。该系统在行为上与 POSIX 文件描述符 (FD) 不兼容。因此,C 运行时 (CRT) 有一个“低 I/O”兼容层,将 POSIX 风格的 FD 与 Windows 文件句柄相关联,它还实现了 POSIX I/O 函数,例如 open。 CRT 的 _open_osfhandle 函数将 native 文件句柄与 FD 相关联,而 _get_osfhandle 返回与 FD 相关联的句柄。有时 CPython 使用 CRT 低 I/O 层,有时它直接使用 Windows API。如果你问我的话,这真的有点乱。

关于Windows "Handle Invalid"上的 Python 将标准输出重定向到文件时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52373180/

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