用于 Windows 的 python os.mkfifo()
简短版本(如果你能回答简短版本,它可以为我完成工作,其余的主要是为了其他具有类似任务的人的利益):
在 Windows 中的 python 中,我想创建 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
Short version (if you can answer the short version it does the job for me, the rest is mainly for the benefit of other people with a similar task):
In python in Windows, I want to create 2 file objects, attached to the same file (it doesn't have to be an actual file on the hard-drive), one for reading and one for writing, such that if the reading end tries to read it will never get EOF (it will just block until something is written). I think in linux os.mkfifo() would do the job, but in Windows it doesn't exist. What can be done? (I must use file-objects).
Some extra details:
I have a python module (not written by me) that plays a certain game through stdin and stdout (using raw_input() and print). I also have a Windows executable playing the same game, through stdin and stdout as well. I want to make them play one against the other, and log all their communication.
Here's the code I can write (the get_fifo()
function is not implemented, because that's what I don't know to do 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
看了上面两个答案,无意间碰到了答案。 os.pipe() 完成了这项工作。谢谢您的回答。
我发布完整的代码以防其他人正在寻找这个:
Following the two answers above, I accidentally bumped into the answer. os.pipe() does the job. Thank you for your answers.
I'm posting the complete code in case someone else is looking for this:
对于跨平台解决方案,我建议在本地主机(127.0.0.1)上的套接字之上构建类似文件的对象——这就是IDLE默认所做的,以解决与您的问题非常相似的问题。
For a cross-platform solution, I'd recommend building the file-like object on top of a socket on localhost (127.0.0.1) -- that's what IDLE does by default to solve a problem that's quite similar to yours.
在 Windows 上,您正在查看 (命名或匿名)管道。
要使用 Windows Pipes,您可以使用 Python for Windows 扩展 (pywin32),或 Ctypes 模块。一个特殊的实用程序模块 win32pipe 提供了 win32 管道的接口蜜蜂。它包括
popen[234]()
便利函数的实现。请参阅如何使用-win32-apis-with-python和类似的SO问题(不是特定于管道,但指向有用的信息)。
On Windows, you are looking at (Named or Anonymous) Pipes.
To work with Windows Pipes, you can use Python for Windows extensions (pywin32), or the Ctypes module. A special utility module, win32pipe, provides an interface to the win32 pipe API's. It includes implementations of the
popen[234]()
convenience functions.See how-to-use-win32-apis-with-python and similar SO questions (not specific to Pipes, but points to useful info).
os.pipe() 返回一个匿名管道,它非常轻量且高效。 (在 Windows 上,“匿名管道是使用具有唯一名称的命名管道。”)
TCP 套接字(如 user1495323 建议)更加重量级:例如,您可以使用 netstat 查看它们,每个端口都需要一个端口号,并且每个对等点的可用端口数限制为 64k(例如从 localhost 到 localhost 的 64k)。
另一方面,命名管道(在 Windows 上)受到限制,因为:
并且可以使用 makefile() 将套接字包装在与 Python 兼容的文件句柄中,这样就可以使用它们重定向 stdout 或 stderr。这使得这对于某些用例来说是一种有吸引力的选择,例如从一个线程发送 stdout 到另一个线程。
可以使用自动分配的端口号来构造套接字,如下所示(基于 优秀的Python套接字HOWTO):
input_socket
的用户(例如另一个线程)可以执行以下操作:os.pipe()
returns an anonymous pipe, which is very lightweight and efficient. (On Windows, "Anonymous pipes are implemented using a named pipe with a unique name.")TCP sockets (as suggested by user1495323) are more heavyweight: you can see them with netstat for example, and each one requires a port number, and the number of available ports is limited to 64k per peer (e.g. 64k from localhost to localhost).
On the other hand, named pipes (on Windows) are limited because:
read()
with a timeout, andAnd sockets can be wrapped in Python-compatible filehandles using
makefile()
, which allows them to be used to redirect stdout or stderr. This makes this an attractive option for some use cases, such as sendingstdout
from one thread to another.A socket can be constructed with an automatically-assigned port number like this (based on the excellent Python socket HOWTO):
The user of
input_socket
(e.g. another thread) can then do: