0

I have such code

downloading(HUGE_FILE)

input_var = raw_input("Enter:")

but the problem is while downloading() function is in progress, if I press enter key, the enter key inserted to input_var.

This is not what I want. I want to receive input after downloading() is completed.

Sungguk Lim
  • 6,109
  • 7
  • 43
  • 63
  • try to check this out: http://stackoverflow.com/questions/8953119/python-waiting-for-external-launched-process-finish – Yohanes Khosiawan 许先汉 Nov 18 '14 at 01:50
  • The keystrokes are buffered by the OS. You'll need to devise some way to flush stdin immediately prior to asking for input. [See also](http://stackoverflow.com/questions/2520893/how-to-flush-the-input-stream-in-python) – John Mee Nov 18 '14 at 01:55
  • Why not just input a pause until the download is done if its an async process? – Greg Nov 18 '14 at 01:56
  • It sounds like you need block until `downloading()` is finished, or have a busy-loop that checks if `downloading()` is finished. Whether or not this is even possible depends on what is happening inside of `downloading()`, so can you show us how you're doing the downloading? – Mike Ounsworth Nov 18 '14 at 02:16
  • Thank you for the comment everybody. I'll try all of them – Sungguk Lim Nov 18 '14 at 02:17
  • There's really no way to do this purely cross-platform in Python 2.x. (And if you want a platform-specific answer, you'll have to tell us what platform(s) you care about.) – abarnert Nov 18 '14 at 02:22

1 Answers1

2

There's no cross-platform way to do this in Python 2.x, because file objects, including stdin, are basically a thin wrapper around a lowest-common-denominator version of C stdio.

However, there are solutions for most *nix systems, and maybe for Windows, and between them, that covers everything you're likely to run a Python terminal program on.


On most *nix systems (pretty much everything you're likely to care about but Windows), if you only care about interactive input (that is, you want to skip anything the user types at the prompt, but don't want to skip anything if piped input from a file or another program), you can do this with the termios library:

downloading(HUGE_FILE)
if sys.stdin.isatty():
    sys.stdin.flush()
    termios.flush(sys.stdin, termios.TCIFLUSH)
    sys.stdin.flush()
input_var = raw_input("Enter:")

There are some edge cases where this may not work. Also, it can break readline support on some platforms. But it will mostly work.


On Windows, it's not quite as simple—but if stdin is the real console input, you can manually drain characters until there are no more by using the Console I/O APIs.

downloading(HUGE_FILE)
if sys.stdin.isatty():
    sys.stdin.flush()
    while msvcrt.kbhit():
        msvcrt.getch()
    sys.stdin.flush()
input_var = raw_input("Enter:")

On both platforms, the stdin.flush calls probably aren't necessary, but in theory it's illegal to switch between terminal/console I/O and stdio I/O without flushing, and in some edge cases you may end up with stuff that's already been read into the buffer that doesn't get thrown away if you don't do it, so, better safe than sorry.


So, how do you know which platform you're on? You could check platform.system() or similar, but it's probably best to just check for the libraries you want to use (especially because there's a whole slew of Unix-like systems you'd have to check for, and not all of them have termios, and some even have it optionally or only as of a certain version or …).

try:
    import termios
    # You can use the Unix code
except ImportError:
    try:
        import msvcrt
        # You can use the Windows code
    except ImportError:
        # You can't use either, just accept the extra characters
abarnert
  • 354,177
  • 51
  • 601
  • 671