【问题标题】:"Inappropriate ioctl for device" from termios with pipes来自带有管道的 termios 的“设备的 ioctl 不合适”
【发布时间】:2021-09-21 21:55:06
【问题描述】:

我昨天在做一个项目,遇到了一个我以前没有遇到过的问题。我目前正在使用 argparse 来询问输入文件名,并且我正在添加对通过 stdin 将文件管道传输到我的程序的支持。我已经完成了所有设置和工作,除了每当我将文件通过管道传输到我的程序时遇到的这个 termios 问题,我想知道是否有人知道解决方案。我得到的确切错误是

    old_settings = self.termios.tcgetattr(fd)
termios.error: (25, 'Inappropriate ioctl for device')

这特别来自getkey 模块,因为我需要一些非阻塞输入的东西(请随时告诉我更好的选择)。我假设它正在发生,因为它的标准 I/O 流由于管道而没有连接到终端,但我不知道是否有办法真正解决这个问题,我真的找不到任何解决方案堆栈溢出或谷歌。这是一个最小的可重现示例:

# Assuming filename is test.py, running
# python3 test.py
# works, but running
# cat test.py | python3 test.py
# or
# python3 test.py < test.py
# results in an error
import sys
import termios

termios.tcgetattr(sys.stdin.fileno())

【问题讨论】:

  • “除了这个 termios 问题外,我已经全部设置好并正常工作了......” -- 那么你为什么认为你需要获取这些属性?
  • @sawdust 我在帖子中提到了 getkey 模块,这就是导致问题的原因。我对使用不同模块的建议持开放态度,并且编辑 getkey 模块的代码也是一个有效的解决方案,我只是不知道我需要添加什么代码,因为我找不到任何解决此错误的方法跨度>

标签: python pipe stdin ioctl termios


【解决方案1】:

我想出了一个使用pty 模块的解决方案,这是我以前不知道的。我给出的示例可以通过使用pty.fork() 将孩子连接到新的伪终端来修复。这个程序似乎有效:

import pty
import sys, termios

pid = pty.fork()
if not pid:
    # is child
    termios.tcgetattr(sys.stdin.fileno())

如果错误来自使用subprocess 创建的新 python 进程,我还找到了解决方案。此版本利用pty.openpty() 创建一个新的伪终端对。

import subprocess, pty, sys

# Create new tty to handle ioctl errors in termios
master_fd, slave_fd = pty.openpty()

proc = subprocess.Popen([sys.executable, 'my_program.py'], stdin=slave_fd)

希望这对其他人有所帮助。

【讨论】:

    猜你喜欢
    • 2013-01-28
    • 2010-12-08
    • 1970-01-01
    • 2014-09-17
    • 2015-02-03
    • 2021-11-25
    • 2015-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多