Python os.mkfifo () for Windows

Short version (if you can answer the short version, it does the job for me, the rest is mainly for other people with a similar task):

In python on Windows, I want to create 2 file objects attached to one file (it should not be the actual file on the hard drive), one for reading and one for writing, so if the end of reading tries to read, it will never get EOF (it will just block until something is written). I think linux os.mkfifo () will do the job, but on Windows it won't. What can be done? (I have to use file objects).

Additional information: I have a python module (not written by me) that plays a specific game through stdin and stdout (using raw_input () and printing). I also have a Windows executable playing the same game through stdin and stdout. I want them to play against each other and record all their messages.

Here is the code I can write (the function is get_fifo()not implemented, because this is what I do not know to make it Windows):

class Pusher(Thread):
        def __init__(self, source, dest, p1, name):
                Thread.__init__(self)
                self.source = source
                self.dest = dest
                self.name = name
                self.p1 = p1

        def run(self):
                while (self.p1.poll()==None) and\
                      (not self.source.closed) and (not self.source.closed):
                        line = self.source.readline()
                        logging.info('%s: %s' % (self.name, line[:-1]))
                        self.dest.write(line)
                        self.dest.flush()


exe_to_pythonmodule_reader, exe_to_pythonmodule_writer =\
                          get_fifo()
pythonmodule_to_exe_reader, pythonmodule_to_exe_writer =\
                          get_fifo()

p1 = subprocess.Popen(exe, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

old_stdin = sys.stdin
old_stdout = sys.stdout

sys.stdin = exe_to_pythonmodule_reader
sys.stdout = pythonmodule_to_exe_writer

push1 = Pusher(p1.stdout, exe_to_pythonmodule_writer, p1, '1')
push2 = Pusher(pythonmodule_to_exe_reader, p1.stdin, p1, '2')

push1.start()
push2.start()
ret = pythonmodule.play()
sys.stdin = old_stdin
sys.stdout = old_stdout
+4
source share
4 answers

After the two answers above, I accidentally stumbled upon an answer. os.pipe () does its job. Thanks for the answer.

I am posting the full code in case anyone else is looking for this:

import subprocess
from threading import Thread
import time
import sys
import logging
import tempfile
import os

import game_playing_module

class Pusher(Thread):
    def __init__(self, source, dest, proc, name):
        Thread.__init__(self)
        self.source = source
        self.dest = dest
        self.name = name
        self.proc = proc

    def run(self):
        while (self.proc.poll()==None) and\
              (not self.source.closed) and (not self.dest.closed):
            line = self.source.readline()
            logging.info('%s: %s' % (self.name, line[:-1]))
            self.dest.write(line)
            self.dest.flush()

def get_reader_writer():
    fd_read, fd_write = os.pipe()
    return os.fdopen(fd_read, 'r'), os.fdopen(fd_write, 'w')

def connect(exe):
    logging.basicConfig(level=logging.DEBUG,\
                        format='%(message)s',\
                        filename=LOG_FILE_NAME,
                        filemode='w')

    program_to_grader_reader, program_to_grader_writer =\
                              get_reader_writer()

    grader_to_program_reader, grader_to_program_writer =\
                              get_reader_writer()

    p1 = subprocess.Popen(exe, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)        

    old_stdin = sys.stdin
    old_stdout = sys.stdout

    sys.stdin = program_to_grader_reader
    sys.stdout = grader_to_program_writer

    push1 = Pusher(p1.stdout, program_to_grader_writer, p1, '1')
    push2 = Pusher(grader_to_program_reader, p1.stdin, p1, '2')

    push1.start()
    push2.start()

    game_playing_module.play()

    sys.stdin = old_stdin
    sys.stdout = old_stdout

    fil = file(LOG_FILE, 'r')
    data = fil.read()
    fil.close()
    return data

if __name__=='__main__':
    if len(sys.argv) != 2:
        print 'Usage: connect.py exe'
        print sys.argv
        exit()
    print sys.argv
    print connect(sys.argv[1])
+13
source

- - localhost (127.0.0.1) - , IDLE , .

+5

Windows (Named Anonymous) Pipes.

- , . , , . , , . , .

Windows Pipes, Python Windows (pywin32) Ctypes. win32pipe API- win32. popen[234]().

. how-to-use-win32-apis-with-python SO ( Pipes, ).

+4

os.pipe() Windows, .

TCP ( user1495323) : , netstat, , 64k (, 64k localhost localhost).

, ( Windows) , :

Python- makefile() makefile(), stdout stderr. , stdout .

, ( Python socket HOWTO):

with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as input_socket:
    # Avoid socket exhaustion by setting SO_REUSEADDR <https://stackoverflow.com/a/12362623/648162>:
    input_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    # localhost doesn't work if the definition is missing from the hosts file,
    # and 127.0.0.1 only works with IPv4 loopback, but socket.gethostname()
    # should always work:
    input_socket.bind((socket.gethostname(), 0))
    random_port_number = input_socket.getsockname()[1]
    input_socket.listen(1)

    # Do something with input_socket, for example pass it to another thread.

    output_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # close() should not strictly be necessary here, but since connect() could fail, it avoids leaking fds
    # in that case. "If a file descriptor is given, it is closed when the returned I/O object is closed".
    with output_socket:
        output_socket.connect((socket.gethostname(), random_port_number))

input_socket (, ) :

with input_socket:
    while True:
        readables, _, _ = select.select([input_socket], [], [input_socket], 1.0)

        if len(readables) > 0:
            input_conn, addr = self.input_socket.accept()
            break

    with input_conn:
        while True:
            readables, _, errored = select.select([input_conn], [], [input_conn], 1.0)
            if len(errored) > 0:
                print("connection errored, stopping")
                break

            if len(readables) > 0:
                read_data = input_conn.recv(1024)
                if len(read_data) == 0:
                    print("connection closed, stopping")
                    break
                else:
                    print(f"read data: {read_data!r}")
0

Source: https://habr.com/ru/post/1747386/


All Articles