代码之家  ›  专栏  ›  技术社区  ›  jsbueno

打印或写入stdout时出现BlockingIOError

  •  0
  • jsbueno  · 技术社区  · 4 年前

    当我从需要终端处于“原始”模式的程序向tty写入数据时,我在网络上得到的“BlockingIOError”记录很少,也不多。

    在Unix(Linux、Mac)中将终端切换到raw是显示行的方法 不打印换行符,更重要的是,可以阅读键入的任何内容 无需等待 <enter> 钥匙。

    检查 https://stackoverflow.com/a/6599441/108205 在Python中实现它的可靠方法。

    然而,当将数据打印到原始终端时,我会在随机时间让我的程序以 BlockingIOError 例外情况。

    (我甚至构建了一个重试机制来解决这个问题,但有时它根本无法解决)。

    异常出现在github上的一些问题中,没有关于如何修复它的断言。 在我的项目中触发它的方法是:

    import terminedia as TM
    
    with TM.keyboard:  # enables the use of TM.inkey() for realtime keyboard reading
        print("*" * 100_000)
    

    (你可以 pip install terminedia 尝试)

    1 回复  |  直到 4 年前
        1
  •  1
  •   jsbueno    4 年前

    这个代码片段创建了一个上下文管理器,它将tty暂时切换回“正常”阻塞模式,包装了具有大量输出的部分,为我解决了这个问题:

    import fcntl
    import os
    ...
    
    class UnblockTTY:
    
        def __enter__(self):
            self.fd = sys.stdin.fileno()
            self.flags_save = fcntl.fcntl(self.fd, fcntl.F_GETFL)
            flags = self.flags_save & ~os.O_NONBLOCK
            fcntl.fcntl(self.fd, fcntl.F_SETFL, flags)
    
        def __exit__(self, *args):
            fcntl.fcntl(self.fd, fcntl.F_SETFL, self.flags_save)
    

    为了完整起见,问题中的代码片段将用以下方式修复:

    import terminedia as TM
    
    with TM.keyboard:  
        with TM.terminal.UnblockTTY():
            print("*" * 100_000)
    

    (尽管在使用termidia时,应该使用“Screen”类,而不是 TM.print 它们已经被包裹了)