Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

select and Pipes trouble in Python

As an extension to a previous post that unfortunately seems to have died a death: select.select issue for sockets and pipes. Since this post I have been trying various things to no avail and I wanted to see if anyone has any idea where I am going wrong. I'm using the select() module to identify when data is present on either a pipe or a socket. The socket seems to be working fine but the pipe is proving problematic.

I have set up the pipe as follows:

pipe_name = 'testpipe'
if not os.path.exists(pipe_name):
    os.mkfifo(pipe_name)

and the pipe read is:

pipein = open(pipe_name, 'r')
line = pipein.readline()[:-1]
pipein.close()

It works perfectly as a stand alone piece of code but when I try and link it to the select.select function it fails:

inputdata,outputdata,exceptions = select.select([tcpCliSock,xxxx],[],[])

I have tried entering 'pipe_name', 'testpipe' and 'pipein' in the inputdata argument but I always get a 'not defined' error. Looking at various other posts I thought it might be because the pipe does not have an object identifier so I tried:

pipein = os.open(pipe_name, 'r')
fo = pipein.fileno()

and put 'fo' in the select.select arguments but got a TypeError: an integer is required. I have also had a Error 9: Bad file descriptor when using this configuration of 'fo'. Any ideas what I have done wrong would be appreciated.

EDITED CODE: I have managed to find a way to resolve it although not sure it is particularly neat - I would be interested in any comments- Revised pipe setup:

pipe_name = 'testpipe'
pipein = os.open(pipe_name, os.O_RDONLY)
if not os.path.exists(pipe_name):
    os.mkfifo(pipe_name)

Pipe Read:

def readPipe()
    line = os.read(pipein, 1094)
    if not line:
        return
    else:
        print line

Main loop to monitor events:

inputdata, outputdata,exceptions = select.select([tcpCliSock,pipein],[],[])
if tcpCliSock in inputdata:
    readTCP()   #function and declarations not shown
if pipein in inputdata:
    readPipe()

It all works well, my only problem now is getting the code to read from the socket before any event monitoring from select gets underway. As soon as connection is made to the TCP server a command is sent via the socket and I seem to have to wait until the pipe has been read for the first time before this command comes through.

like image 659
AimSkyward Avatar asked Nov 01 '22 14:11

AimSkyward


1 Answers

According to the docs, select needs a file descriptor from os.open or similar. So, you should use select.select([pipein], [], []) as your command.

Alternatively, you can use epoll if you are on a linux system.

poller = epoll.fromfd(pipein)
events = poller.poll()
for fileno, event in events:
  if event is select.EPOLLIN:
    print "We can read from", fileno
like image 174
Spencer Rathbun Avatar answered Nov 09 '22 15:11

Spencer Rathbun