Reputation: 830
I'm hot on the trail of figuring something out for one of my projects, but hung up on one issue:
I'm using a FIFO operation to send a 'signal' (simple T/F) from one module to another. One module opens the FIFO to write to it, and the other opens the FIFO to read from it. The goal here is to have the reading module immediately read and display as soon as the writing module receives the command to do so. The writing module opens the FIFO, but the reading module doesn't seem to do so.
Is what I'm trying to do even possible? I'm trying to spin both operations in _threads in order to keep multiple processes going in each module. Note both modules are in classes that I didn't include for the sake of brevity (explaining 'self').
def pipe_relay(self):
FIFO = 'pipe_relay'
thread_num = num
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
while self.relay_switch:
print("Opening FIFO...")
with open(FIFO) as fifo:
print("FIFO opened")
while self.relay_switch:
data = fifo.write(signal)
if len(data) == 0:
print("Writer is closed")
break
print('Write: "{0}"'.format(data))
I realized that I didn't want to be writing to the FIFO continuously with the data I threw at it, so I removed the while() statement. Now, it doesn't seem as though the FIFO will open at all...
def pipe_relay(self, num, signal):
FIFO = 'pipe_relay'
thread_num = num
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
print("Opening FIFO...")
# does not proceed past this point
with open(FIFO, mode = 'w') as fifo:
print("FIFO opened")
data = fifo.write(signal)
if len(data) == 0:
print("Writer is closed")
print('Write: "{0}"'.format(data))
fifo.close()
def pipe_receive(self):
FIFO = 'pipe_relay'
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
# module proceeds to here, but no further
with open(FIFO) as fifo:
print("FIFO opened (receiver)")
while True:
data = fifo.read()
if len(data) == 0:
print("Writer is closed")
break
print('Read signal: "{0}"'.format(data))
self.DISPLAY['text'] = data
print("this is in 'pipe_receieve'")
EDIT
Running Ubuntu 17.04. The project is written for the Python 3.5 interpreter.
Upvotes: 4
Views: 4514
Reputation: 22438
Here are simple send and get snippets written using Python 3.5.2
.
Comment out the fifo.flush()
line and see the difference in behaviour.
With flush
the get code operates in tandem with the send code.
Without it, the get code does not react until the fifo is closed
send.py
import sys, os, time
path = "/tmp/my.fifo"
try:
os.mkfifo(path)
except:
pass
try:
fifo = open(path, "w")
except Exception as e:
print (e)
sys.exit()
x = 0
while x < 5:
fifo.write(str(x))
fifo.flush()
print ("Sending:", str(x))
x+=1
time.sleep(3)
print ("Closing")
fifo.close()
try:
os.unlink(fifo)
except:
pass
get.py
import os, sys
path = "/tmp/my.fifo"
try:
fifo = open(path, "r")
except Exception as e:
print (e)
sys.exit()
while True:
r = fifo.read(1)
if len(r) != 1:
print ("Sender Terminated")
break
print ("Received:", r)
fifo.close()
Upvotes: 4
Reputation: 867
In addition to requiring the 'w'
option to the sending module, you may also be having issues with either the sending or receiver not being connected. In order for another process to make use of a fifo, both the sender and receiver must have the fifo handle open.
See the linux documentation on a fifo. If the receiver is not listening, you get a SIGPIPE which typically will terminate a process but in python's case it will wait until a receiver is connected.
If your sender is dead and the listener is still active it received an EOF and stops reading.
Upvotes: 2
Reputation: 930
I'm a bit surprised that the code doesn't raise an exception. In your writer, you do a regular open(FILO)
, without specifying the mode
parameter. According to the documentation, mode
defaults to r
(read-only), so I would expect the fifo.write(signal)
to raise an IOError
. Are Exceptions being caught somewhere?
Either way, you should add a mode="w"
to the writer-side to open the FIFO for writing.
Upvotes: 0