1

I am communicating between two python scripts via pipes (Python 3.6.0 on osx). In the ideal case where the message is sent and waiting in the pipe, reading it isn't a problem. However when the pipe is empty it hangs while trying to read it.

Here is the script that writes to the pipe:

import pipes
pipe_path = "/tmp/mypipe"
t = pipes.Template()
t.append('tr a-z A-Z', '--')
f = t.open(pipe_path, 'w')
f.write('ping')

Here is the script that that reads it:

import pipes
pipe_path = "/tmp/mypipe"
t = pipes.Template()
t.append('tr a-z A-Z', '--')
f = t.open(pipe_path, 'r')
txt = f.read()
print(txt)

So if I run the second script without running the first one it hangs. How can I detect if the pipe is empty and avoid it hanging on f.read()?

  • I scanned through the duplicate answer and didn't see this mentioned, so I thought you might want to hear it explicitly right up front...it basically never makes sense to call read() and not expect to read something or to get back a EOF because the pipe has been closed on the writer side. All of the answers in the duplicate will make this assumption. It's just the way read() is meant to be used. - read can't know when to give up waiting for data on a pipe that never closes. - the other gotcha is that you can't assume that when read() returns, all the data that you want has been received. – CryptoFool Jun 06 '19 at 02:08
  • 1
    Thanks Steve. That is helpful to hear that specifically. I sifted through the duplicate question and tried to apply the code to my situation. It is different because it is communicating via pipes between a python script and an executable. Whereas I am working between two python scripts. For the time being I am simply going to write to the pipe before I attempt to read to it, to avoid hanging on a closed/empty pipe. – Caroline Record Jun 06 '19 at 15:28
  • I did a write-up explaining what I said above in more detail, but I couldn't post it because the question was closed. I'd be happy to send it to you. Or just know that because you have to know how much to read, you need to set up a protocol that gives you that. One easy thing is to always send a length word (2 bytes, say) that says how much data is to follow. So then the reader knows to always expect 2 bytes, it reads those bytes, interprets them as a length, and that tells it how much more stuff to read. So your example would send something like "0x00 0x04 p i n g" – CryptoFool Jun 06 '19 at 15:39
  • ...an empty message would be "0x00 0x00". Makes sense? – CryptoFool Jun 06 '19 at 15:41
  • I think that this question was closed too quickly and your case is a bit different...simpler...as you say. As the close message says, if you really think that the duplicate answer didn't address your needs, you could ask a similar question, that maybe stresses that you want to understand this simple case. – CryptoFool Jun 06 '19 at 15:47
  • I just noticed that you say "avoid hanging on a closed/empty pipe". If you can close the pipe on the writer side when you know there's no more data to be written, then your read() won't hang. That is the other way to solve your problem easily and correctly...you then read in a loop until you get back EOF. This is how pipes work in Linux, where there's no protocol, but an understanding that the pipe will be closed when all data has been sent. – CryptoFool Jun 06 '19 at 15:50
  • I tried to close the pipe aka with f.close() as described here- https://docs.python.org/2/library/pipes.html But it also hangs on f.close – Caroline Record Jun 06 '19 at 16:06
  • That's strange. That shouldn't happen. So the example in that document doesn't work for you...it hangs? – CryptoFool Jun 06 '19 at 16:07
  • Trouble is that script A is running till it gets the message from script B to stop. Script B runs once and triggers script A to stop. script A is constantly reading from the pipes to check if has gotten the stop message from B. Having script A write a test character before reading is working fine- it just doesn't seem like the most elegant solution. – Caroline Record Jun 06 '19 at 16:10
  • But shouldn't the EOF be the message to stop, which script A sends by closing the pipe? That way, the code should work without having to send any characters if A has nothing to send. - for example, the code you point to above should work fine even if you take out the write() call so no data is sent. – CryptoFool Jun 06 '19 at 16:13
  • Did some testing and it looks like file path to the pipes was important. when I attempt to save to "/tmp/pipe" it hangs but when I give it a relative path it is fine! – Caroline Record Jun 06 '19 at 16:16
  • Cool! Don't know why that should matter, but if you have a solution that works, that's great. – CryptoFool Jun 06 '19 at 16:17

0 Answers0