0

Some interactive commands output differently if stdin is piped. Why is that?

Below I test subprocess.Popen on 3 different commands, with and without stdin piped.

 
Code:

import subprocess, time


def run_command(command, enable_input):
    print 'command="{}", enable_input={}:'.format(command, enable_input)

    # Launch the process and set up pipes.
    if enable_input:
        stdin = subprocess.PIPE
    else:
        stdin = None
    child = subprocess.Popen(command, stdin=stdin)

    # Wait a second for output.
    time.sleep(1)

    # Terminate the child if it hasn't finished.
    if child.poll() == None:
        child.terminate()

    print '\n-----' # Print a separator


commands = ('cmd', 'python', 'timeout 1')
for command in commands:
    run_command(command, enable_input=False)
    run_command(command, enable_input=True)

 
Output:

command="cmd", enable_input=False:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\>
-----
command="cmd", enable_input=True:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\>
-----
command="python", enable_input=False:
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
-----
command="python", enable_input=True:

-----
command="timeout 1", enable_input=False:

Waiting for 0 seconds, press a key to continue ...

-----
command="timeout 1", enable_input=True:
ERROR: Input redirection is not supported, exiting the process immediately.

-----

 
Answers to the question linked below suggest that some programs try to detect whether they're being run by a human or a script. Is that the case here? And if so, how do they detect that on Windows?

Why does supplying stdin to subprocess.Popen cause what is written to stdout to change?

Community
  • 1
  • 1
Alan L
  • 1,785
  • 19
  • 28

1 Answers1

3

Yes, some programs do behave differently if you are piping or redirecting input. You can detect it like this:

import sys
print sys.stdin.isattty()   # True if it's a terminal, False if it's redirected

This works on *nix as well as on Windows.

kindall
  • 178,883
  • 35
  • 278
  • 309
  • Thank you! In that case, I have another question: Is there a way to masquerade as a terminal (in Windows)? – Alan L Feb 24 '13 at 19:19
  • It's not a great solution, but serial ports may be treated as terminals (depending on the context) so if you're desperate enough you could try using a null-modem emulator such as com0com or a derivative thereof. – Harry Johnston Feb 24 '13 at 23:14
  • I plan to distribute my program, so I think that would add too much bulk. But it is an interesting idea. – Alan L Feb 25 '13 at 00:40