【问题标题】:How to detect that stdio was redirected to nul?如何检测stdio被重定向到nul?
【发布时间】:2015-10-16 09:30:58
【问题描述】:

我正在开发一个包来解决在标准 Windows 控制台环境中运行的 Python 中的 Unicode 的几个问题:https://github.com/Drekin/win-unicode-console。关键操作是在需要时替换标准流对象。为此,我需要检测标准流是否被重定向。 Python 方法 isatty() 工作正常,但有一个例外:如果流被重定向到 nul,则 isatty() 返回 True

我的问题是如何检测 Windows 句柄是通向控制台还是通向nul?有 WinAPI 函数吗?

【问题讨论】:

    标签: python windows winapi stdout


    【解决方案1】:

    C 运行时的 _isatty 函数对于访问字符设备的文件(即 GetFileType 返回 FILE_TYPE_CHAR 的文件)返回 true。要特别检测控制台句柄,您可以调用GetConsoleMode。对于非控制台句柄,此调用失败。要获取底层 Windows 句柄以传递给此函数,请调用 msvcrt.get_osfhandle。例如:

    import ctypes
    import msvcrt
    
    kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
    ERROR_INVALID_HANDLE = 6
    
    def isconsole(fd):
        handle = msvcrt.get_osfhandle(fd)
        if kernel32.GetConsoleMode(handle, ctypes.byref(ctypes.c_uint())):
            return True
        last_error = ctypes.get_last_error()
        if last_error != ERROR_INVALID_HANDLE:
            raise ctypes.WinError(last_error)
        return False
    

    【讨论】:

    • 再次感谢您。我目前分别使用kernel32.GetLastErrorkernel32.GetStdHandle 而不是ctypes.get_last_errormsvcrt.get_osfhandle。有理由偏爱一个吗?
    • @user87690,我可以将答案更改为使用GetStdHandle。 C 运行时尝试使文件描述符 0、1 和 2 与 Windows StandardInputStandardOutputStandardError 保持同步。但是程序可能会绕过 CRT 手动调用SetStdHandle。您更喜欢哪个,使用与 C 标准文件描述符关联的句柄,还是始终使用 Windows 标准句柄?
    • @user87690,至于直接调用GetLastError,一般都可以。但是,高级 Python 语句之间有很多代码,所以我更喜欢用 use_last_error=True 加载 DLL,以在线程局部变量中捕获线程的最后一个错误。 ctypes 在调用目标函数之前通过SetLastError 交换这个线程本地,并在调用之后通过GetLastError 将它交换回来。通过调用ctypes.get_last_errorctypes.set_last_error 访问它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 2012-12-05
    • 2017-07-18
    • 2011-06-01
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多