tags:

views:

855

answers:

3

This code

select.select([sys.stdin], [], [], 1.0)

does exactly what I want on Linux, but not in Windows.

I've used kbhit() in msvcrt before to see if data is available on stdin for reading, but in this case it always returns 0. Additionally msvcrt.getch() returns '\xff' whereas sys.stdin.read(1) returns '\x01'. It seems as if the msvcrt functions are not behaving properly.

Unfortunately I can't use TCP sockets as I'm not in control of the application talking my Python program.

A: 

This functionality is not supported on Windows. Please see http://www.python.org/doc/2.5.2/lib/module-select.html:

Note that on Windows, it [the select module] only works for sockets; on other operating systems, it also works for other file types (in particular, on Unix, it works on pipes). It cannot be used on regular files to determine whether a file has grown since it was last read.

Martin Carpenter
+3  A: 

In some rare situations, you might care what stdin is connected to. Mostly, you don't care -- you just read stdin.

In someprocess | python myprogram.py, stdin is connected to a pipe; in this case, the stdout of the previous process. You simply read from sys.stdin and you're reading from the other process. [Note that in Windows, however, there's still (potentially) a "CON" device with a keyboard. It just won't be sys.stdin.]

In python myprogram.py <someFile, stdin is connected to a file. You simply read from sys.stdin and you're reading from the file.

In python myprogram.py, stdin is left connected to the console (/dev/ttyxx in *nix). You simple read from sys.stdin and you're reading from the keyboard.

Note the common theme in the above three cases. You simply read from sys.stdin and your program's environment defines everything for you. You don't check "to see if data is available on stdin for reading". It's already available.

Sometimes, you want a keyboard interrupt (or other shenanigans). Python, BTW, has a keyboard interrupt as a first-class feature of the I/O elements. Control-C raises an interrupt during I/O (it won't break into a tight loop, but it will signal a program that prints periodically.)

Sometimes you need to find out what kind of file stdin is connected to.

Something like os.isatty( sys.stdin.fileno() ) If sys.stdin is a TTY, you're program was left connected to the windows "CON" (the keyboard). If sys.stdin is not a TTY, it's connected to a file or a pipe.


Example

Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Documents and Settings\slott>python
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import sys
>>> os.isatty( sys.stdin.fileno() )
True
>>>

The value of True tells me Python is running without a file or pipe attached. sys.stdin is the keyboard. Using windows kbhit is needless.

A value of False tells me Python is running with a file or pipe attached. sys.stdin is NOT the keyboard. Checking kbhit might be meaningful. Also, I could open the CON: device and read the keyboard directly, separate from sys.stdin.


I'm not sure why you need "to see if data is available on stdin for reading". It might help to update your question with additional details of what you're trying to accomplish.

S.Lott
os.isatty(sys.stdin.fileno()) returns False
awatts
A: 

I run a thread that reads from stdin, then forward the data to a socket. The socket is selectable, so, stdin is selectable too.

see: http://www.ideawu.com/blog/3.html

ideawu