views:

63

answers:

1

Good day, Stackoverflow!

I have a little (big) problem with porting one of my Python scripts for Linux to Windows. The hairy thing about this is that I have to start a process and redirect all of its streams into pipes that I go over and read and write to and from in my script.

With Linux this is a piece of cake:

server_startcmd = [
           "java", 
           "-Xmx%s" % self.java_heapmax, 
           "-Xms%s" % self.java_heapmin,
           "-jar",
           server_jar,
           "nogui"
        ]

server = Popen(server_startcmd, stdout = PIPE, 
                                stderr = PIPE, 
                                stdin  = PIPE)

outputs = [
     server_socket, # A listener socket that has been setup before
     server.stderr,
     server.stdout,
     sys.stdin # Because I also have to read and process this.
   ]

clients = []

while True:
     read_ready, write_ready, except_ready = select.select(outputs, [], [], 1.0)

     if read_ready == []:
        perform_idle_command() # important step
     else:
        for s in read_ready:
           if s == sys.stdin:
              # Do stdin stuff
           elif s == server_socket:
              # Accept client and add it to 'clients'
           elif s in clients:
              # Got data from one of the clients

The whole 3 way alternating between a server socket, stdin of the script and the output channels of the child process (as well as the input channel, as my script will write to that one, although that one is not in the select() list) is the most important part of the script.

I know that for Windows there is win32pipe in the win32api module. The problem is that finding resources to this API is pretty hard, and what I found was not really helpful.

How do I utilize this win32pipe module to do what I want? I have some sources where it's being used in a different but similar situation, but that confused me pretty much:

if os.name == 'nt':
   import win32pipe
  (stdin, stdout) = win32pipe.popen4(" ".join(server_args))
else:
   server = Popen(server_args,
     stdout = PIPE,
     stdin = PIPE,
     stderr = PIPE)
   outputs = [server.stderr, server.stdout, sys.stdin]
   stdin = server.stdin

[...]

while True:
   try:
      if os.name == 'nt':
         outready = [stdout]
      else:
         outready, inready, exceptready = select.select(outputs, [], [], 1.0)
   except:
      break

stdout here is the combined stdout and stderr of the child process that has been started with win32pipe.popen4(...)

The questions arsing are:

  • Why not select() for the windows version? Does that not work?
  • If you don't use select() there, how can I implement the neccessary timeout that select() provides (which obviously won't work like this here)

Please, help me out!

A: 

I think you cannot use select() on pipes. In one of the projects, where I was porting a linux app to Windows I too had missed this point and had to rewrite the whole logic.

mdk