Я пытаюсь дождаться UNIX FIFO для некоторой входной строки. Я использую select (), чтобы дождаться, пока FD будет готов к чтению. В первый раз мой код ожидает, как и ожидалось, но затем select () продолжает успешно возвращаться, даже если FD больше не готов к чтению.
Вот мой код:
#! /usr/bin/python3
import errno
import time
import sys
import os
import select
import string
myInput = './inFIFO'
try:
if os.path.exists(myInput):
os.unlink(myInput)
os.mkfifo(myInput)
except Exception as e:
sys.stderr.write("ERROR: " + str(e))
sys.exit(2)
sIn = open(myInput, 'r')
try:
loop = 5
while loop:
loop = loop - 1
readMe = select.select([sIn], [], [])[0]
print(readMe, file = sys.stderr);
if len(readMe):
a = sIn.readlines()
print('Message <|' + ''.join(a) + '|>', file = sys.stderr)
sIn.flush()
except Exception as e:
sys.stderr.write('ERROR: ' + str(e))
sys.stdin.close()
sys.stdout.close()
sys.stderr.close()
os.unlink(myStdin)
sys.exit(1)
Вот результат:
root:~# ./select.py &
[1] 4035
root:~# echo 'Hello World !!!' > ./inFIFO
root:~# [<_io.TextIOWrapper name='./inFIFO' mode='r' encoding='UTF-8'>]
Message <|Hello World !!!
|>
[<_io.TextIOWrapper name='./inFIFO' mode='r' encoding='UTF-8'>]
Message <||>
[<_io.TextIOWrapper name='./inFIFO' mode='r' encoding='UTF-8'>]
Message <||>
[<_io.TextIOWrapper name='./inFIFO' mode='r' encoding='UTF-8'>]
Message <||>
[<_io.TextIOWrapper name='./inFIFO' mode='r' encoding='UTF-8'>]
Message <||>
[1]+ Done ./select.py
root:~#
Почему select () ведет себя необычно? Я использую LinuxMint 19 amd64 и Python 3.6.6
Обновлено:
Обновил код с os.read()
все та же история ...
Новый код:
#! /usr/bin/python3
import errno
import time
import sys
import os
import select
import string
myInput = './inFIFO'
try:
if os.path.exists(myInput):
os.unlink(myInput)
os.mkfifo(myInput)
except Exception as e:
sys.stderr.write("ERROR: " + str(e))
sys.exit(2)
sIn = open(myInput, 'r')
try:
loop = 5
while loop:
loop = loop - 1
readMe = select.select([sIn], [], [])[0]
print(readMe, file = sys.stderr);
if len(readMe):
a = os.read(sIn.fileno(), 8192).decode()
print('Message <|' + ''.join(a) + '|>', file = sys.stderr)
sIn.flush()
except Exception as e:
sys.stderr.write('ERROR: ' + str(e))
sys.stdin.close()
sys.stdout.close()
sys.stderr.close()
os.unlink(myStdin)
sys.exit(1)
Теперь вывод:
root:~# ./select.py &
[1] 4099
root:~# echo 'Hello World !!!' > ./inFIFO
root:~# [<_io.TextIOWrapper name='./inFIFO' mode='r' encoding='UTF-8'>]
Message <|Hello World !!!
|>
[<_io.TextIOWrapper name='./inFIFO' mode='r' encoding='UTF-8'>]
Message <||>
[<_io.TextIOWrapper name='./inFIFO' mode='r' encoding='UTF-8'>]
Message <||>
[<_io.TextIOWrapper name='./inFIFO' mode='r' encoding='UTF-8'>]
Message <||>
[<_io.TextIOWrapper name='./inFIFO' mode='r' encoding='UTF-8'>]
Message <||>
[1]+ Done ./select.py
root:~#
Мне удалось решить проблему, открыв FIFO как READ-WRITE и NON-BLOCK I / O.
Мой рабочий код:
#! /usr/bin/python3
import errno
import time
import sys
import os
import select
import string
myInput = './inFIFO'
try:
if os.path.exists(myInput):
os.unlink(myInput)
os.mkfifo(myInput)
except Exception as e:
sys.stderr.write("ERROR: " + str(e))
sys.exit(2)
inFD = os.open(myInput, os.O_RDWR | os.O_NONBLOCK)
sIn = os.fdopen(inFD, 'r')
try:
loop = 5
while loop:
loop = loop - 1
readMe = select.select([sIn], [], [])[0]
print(readMe, file = sys.stderr);
if len(readMe):
a = sIn.read()
print('Message <|' + ''.join(a) + '|>', file = sys.stderr)
except Exception as e:
sys.stderr.write('ERROR: ' + str(e))
sys.stdin.close()
sys.stdout.close()
sys.stderr.close()
os.unlink(myStdin)
sys.exit(1)
Выход:
root:~# ./select.py &
[1] 4179
root:~# echo 'Hello World !!!' > ./inFIFO
root:~# [<_io.TextIOWrapper name=3 mode='r' encoding='UTF-8'>]
Message <|Hello World !!!
|>
root:~# echo 'Hello World !!!' > ./inFIFO
[<_io.TextIOWrapper name=3 mode='r' encoding='UTF-8'>]
Message <|Hello World !!!
|>
root:~#
Не используйте буферизованный ввод-вывод (
.readlines
) сselect.select
, они могут странно взаимодействовать. Вместо этого используйтеos.read
. Пожалуйста, расширьте вопрос с помощью вывода на консоль после заменыsIn.readlines()
наos.read(sIn.fileno(), 8192)
.