Tabulate
Tabulate

Reputation: 641

"Inappropriate ioctl for device" from termios with pipes

I was working on a project yesterday and I came across an issue that I haven't encountered before. I'm current using argparse to ask for an input filename, and I'm adding support for piping a file via stdin to my program. I've got it all set up and working, except for this termios issue I'm encountering whenever I pipe a file to my program, and I was wondering if anyone knows a solution. The exact error I'm getting is

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

This specifically is coming from the getkey module, because I need something for non-blocking input (feel free to inform me of better options). I'm assuming it's happening because its standard I/O streams aren't connected to a terminal because of the pipe, but I don't know if there's a way I can actually fix that and I can't really find any solutions on stackoverflow or Google. Here's a minimal reproducible example:

# 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())

Upvotes: 3

Views: 5676

Answers (1)

Tabulate
Tabulate

Reputation: 641

I figured out a solution using the pty module which I didn't know about before. The example I gave can be fixed by using pty.fork() to connect the child to a new pseudo-terminal. This program seemed to work:

import pty
import sys, termios

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

I also found a solution for if the error is coming from a new python process created with subprocess. This version utilizes pty.openpty() to create a new pseudo-terminal pair.

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)

Hope this helps someone else out.

Upvotes: 5

Related Questions