"Inappropriate ioctl for device" 来自带管道的 termios
"Inappropriate ioctl for device" from termios with pipes
昨天我在做一个项目,遇到了一个以前没有遇到过的问题。我目前正在使用 argparse 来请求输入文件名,并且正在添加对通过 stdin 将文件传输到我的程序的支持。我已经设置好一切并正常工作,除了每当我将文件通过管道传输到我的程序时遇到的这个 termios 问题,我想知道是否有人知道解决方案。我得到的确切错误是
old_settings = self.termios.tcgetattr(fd)
termios.error: (25, 'Inappropriate ioctl for device')
这特别来自 getkey 模块,因为我需要一些非阻塞输入的东西(请随时告诉我更好的选择)。我假设它正在发生,因为它的标准 I/O 流由于管道的原因没有连接到终端,但我不知道是否有办法真正解决这个问题而且我真的找不到任何Whosebug 或 Google 上的解决方案。这是一个最小的可重现示例:
# 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())
我找到了一个使用 pty
模块的解决方案,这是我以前不知道的。我给出的示例可以通过使用 pty.fork()
将 child 连接到新的 pseudo-terminal 来修复。这个程序似乎有效:
import pty
import sys, termios
pid = pty.fork()
if not pid:
# is child
termios.tcgetattr(sys.stdin.fileno())
如果错误来自使用 subprocess
创建的新 python 进程,我还找到了解决方案。此版本利用 pty.openpty()
创建新的 pseudo-terminal 对。
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)
希望这对其他人有所帮助。
昨天我在做一个项目,遇到了一个以前没有遇到过的问题。我目前正在使用 argparse 来请求输入文件名,并且正在添加对通过 stdin 将文件传输到我的程序的支持。我已经设置好一切并正常工作,除了每当我将文件通过管道传输到我的程序时遇到的这个 termios 问题,我想知道是否有人知道解决方案。我得到的确切错误是
old_settings = self.termios.tcgetattr(fd)
termios.error: (25, 'Inappropriate ioctl for device')
这特别来自 getkey 模块,因为我需要一些非阻塞输入的东西(请随时告诉我更好的选择)。我假设它正在发生,因为它的标准 I/O 流由于管道的原因没有连接到终端,但我不知道是否有办法真正解决这个问题而且我真的找不到任何Whosebug 或 Google 上的解决方案。这是一个最小的可重现示例:
# 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())
我找到了一个使用 pty
模块的解决方案,这是我以前不知道的。我给出的示例可以通过使用 pty.fork()
将 child 连接到新的 pseudo-terminal 来修复。这个程序似乎有效:
import pty
import sys, termios
pid = pty.fork()
if not pid:
# is child
termios.tcgetattr(sys.stdin.fileno())
如果错误来自使用 subprocess
创建的新 python 进程,我还找到了解决方案。此版本利用 pty.openpty()
创建新的 pseudo-terminal 对。
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)
希望这对其他人有所帮助。