2010-05-27 137 views
3

短版(如果你能回答的短版它確實爲我工作,其餘主要是爲其他人有類似的任務受益):蟒蛇os.mkfifo()用於Windows

在蟒蛇在Windows中,我要創建2個文件對象,連接到同一個文件(它不必是硬盤驅動器上的實際文件),一個用於讀取,一個用於寫入,這樣,如果讀取結束嘗試閱讀它永遠不會得到EOF(它會阻止,直到寫入東西)。我認爲在linux os.mkfifo()會做這項工作,但在Windows中它不存在。可以做什麼? (我必須使用文件對象)。

一些額外的細節: 我有一個python模塊(不是我寫的)通過stdin和stdout(使用raw_input()和print)來玩特定的遊戲。我也有一個Windows可執行文件通過stdin和stdout來玩同一個遊戲。我想讓他們互相對抗,並記錄他們所有的交流。

這是我能寫的代碼(get_fifo()功能沒有實現,因爲這是我不知道這樣做的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 
+0

你試圖放棄'get_fifo()'和'連接與pythonmodule'的Windows可執行文件直接:'SYS。 stdin,sys.stdout = p1.stdout,p1.stdin'。一切''通過pythonmodule' print'ed寫入'p1.stdin'和的raw_input'()''從p1.stdout'在這種情況下讀取。如果由於Python端的緩衝問題而失敗;嘗試使用無緩衝標準輸入/輸出運行腳本:'蟒蛇-u your_script.py'並添加'BUFSIZE = 0'參數'Popen'。 – jfs 2013-12-20 11:15:10

回答

11

遵循上述兩個答案,我不小心撞到了答案。 os.pipe()完成這項工作。謝謝您的回答。

我張貼的情況下,別人的完整代碼正在尋找這樣的:

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.source.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]) 
+3

+1自我回答適合於計算器 – msw 2010-05-27 16:20:12

4

在Windows上,你在看(Named or Anonymous) Pipes

管道是處理用於通信的共享內存的一部分。創建管道的過程是管道服務器。連接到管道的進程是管道客戶端。一個進程將信息寫入管道,然後另一個進程從管道讀取信息。

要使用Windows管道的工作,你可以使用Python for Windows extensions (pywin32),或Ctypes module。一個特殊的實用程序模塊win32pipe提供了一個到win32管道API的接口。它包括popen[234]()便利功能的實現。

how-to-use-win32-apis-with-python和SO類似的問題(不是特定於管道,但點有用的信息)。

+0

所以,....爲什麼地球上不能蟒蛇只是代碼複製粘貼到自己的mkfifo功能? – 2017-10-22 23:45:01

4

對於跨平臺的解決方案,我建議在localhost(127.0.0.1)上的套接字之上構建類文件對象 - 這是IDLE默認可以解決與您的問題非常相似的問題。

+0

好主意!當TCP套接字完全相同時,無需使用管道。 – user1495323 2015-07-13 01:09:35