Reputation: 5856
I have a python script that publishes messages that are read from stdin onto a message queue in the network. However, if there wasn't any message on the pipe for a specified amount of time I have to send a heartbeat.
So I have to distinguish between 3 cases:
Currently, my code looks as follow:
import sys
for i, line in enumerate(sys.stdin):
connection.publish(line)
connection.close()
However I need to interrupt the for look if there was any timeout. I.e. sys.stdin
has not delivered any data for some time.
Upvotes: 6
Views: 4607
Reputation: 226
A python3 version of the OP's answer without using exception handling:
import sys
import select
while True:
if select.select([sys.stdin,],[],[],2.0)[0]:
line = sys.stdin.readline()
if line:
print('Got:', line, end='')
else:
print('EOF!')
break
else:
print('No data for 2 secs')
Upvotes: -1
Reputation: 3714
If anybody is looking for a portable solution, this is what I came up with
after lots of trial and error.
It requires the pywin32
pypi package to work on windows
import os, sys
if sys.platform == "win32":
import win32api, win32event, win32file, pywintypes
else:
import select
def stdin_has_content(timeout: float) -> bool:
assert timeout >= 0
if sys.platform == "win32":
try:
# without this flush, WaitForSingleObject might return early
win32file.FlushFileBuffers(win32api.STD_INPUT_HANDLE)
except pywintypes.error:
pass # this happens if stdin is already closed, but that's ok
return win32event.WaitForSingleObject(
win32api.STD_INPUT_HANDLE, int(timeout * 1000)
) == win32event.WAIT_OBJECT_0
else:
rlist, _, _ = select.select([sys.stdin], [], [], timeout)
return bool(rlist)
Upvotes: 3
Reputation: 5856
This is what I finally came up with
import sys
import select
while True:
try:
if select.select([sys.stdin,],[],[],2.0)[0]:
line = sys.stdin.next()
print "Got:", line
else:
print "No data for 2 secs"
except StopIteration:
print 'EOF!'
break
Upvotes: 8