Hello! I'm trying to run a subprocess (actually several), and control their terminals (not just stdin and stdout). I have a use case, but I won't bore everyone with those details.
I'd rather not use pexpect or ptyprocess, because those expose a very different interface than Popen. I've mostly acheived my goals with the following wrapper around subprocess: > import subprocess, pty, fcntl, termios, os > TTY = 'termyTTY' > > def Popen(cmd, **kwargs): > tty = kwargs.pop('tty', None) > if tty is not None: > if tty is True: > tty = pty.openpty() > master_fd, slave_fd = tty > old_preexec = kwargs.get('preexec_fn') > def preexec_fn(): > if old_preexec: > old_preexec() > fcntl.ioctl(slave_fd, termios.TIOCSCTTY) > kwargs['preexec_fn'] = preexec_fn > kwargs['start_new_session'] = True > for stkind in ('stdin', 'stdout', 'stderr'): > if kwargs.get(stkind, None) != TTY: > continue > kwargs[stkind] = slave_fd > > proc = subprocess.Popen(cmd, **kwargs) > if tty is not None: > proc.tty = master_fd > os.close(slave_fd) > return proc This adds a tty keyword argument that spawns a new controlling TTY and switches the new process to it. It also allows setting stdin/etc. separately. You can, for instance, run ssh and send it a password through the tty channel, and separately receive piped output from the remote ssh command. My questions: 1. Is this already available in a simple way somewhere else, preferably with a Popen-compatible interface? 2. Is this preexec_fn sufficiently simple that it does not run afoul of the big, scary threading warning of _posixsubprocess.fork_exec ? I.e., I'm not touching any locks (besides the GIL... but I'm assuming that would be properly handled?). CAN this be made safe? I do plan to use threads and locks. 3. Does this seem widely useful enough to be worth trying to get into Python itself? It would be nice if this specific behavior, which probably has even more nuances than I already am aware of, were safely achievable out of the box. Best, Antonio -- https://mail.python.org/mailman/listinfo/python-list