Python和Windows命名管道 [英] Python and Windows Named Pipes

查看:440
本文介绍了Python和Windows命名管道的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过Python与Windows上的命名管道进行通信的正确方法是什么?我已经用谷歌搜索了,找不到任何包装此通信的软件包.

What is the proper way of communicating with named pipes on Windows from Python? I've googled it, and can't find any packages that wrap this communication.

有:

  • some descriptions of how to do it with pywin32 (I could not find how to connect to an existing pipe with it, though).
  • This package: https://pypi.python.org/pypi/PyWPipe/ (had no luck with it either)
  • A piece of code here, that I haven't yet tested: http://jonathonreinhart.blogspot.ru/2012/12/named-pipes-between-c-and-python.html

我只需要连接到现有的命名管道并对其进行读/写操作.我以前只尝试使用串行端口进行通信(使用pySerial),与之相比,我很惊讶在命名管道上找不到多少信息.通常,有大量针对Python的各种用途的指南.

I need just to connect to an existing named pipe and read/write to it. I previously had only tried communication with serial port (using pySerial), and I'm surprised how little info I could find on named pipes in comparison to it. There's usually tons of guides for any purpose for Python.

我将不胜感激.

推荐答案

为了连接到现有的命名管道,您可以使用通过pywin32包提供的CreateFile API.由于花了我一些时间将工作基础放在一起,因此这里有一个示例客户端/服务器,它对我来说很好用(在Windows 10 Pro x64上为python 3.6.5,pywin32 223):

In order to connect to an existing named pipe you can utilize the CreateFile API provided through the pywin32 package. Since it took me a while to put a working base together here is an example client/server which works fine for me (python 3.6.5, pywin32 223 on Windows 10 Pro x64):

import time
import sys
import win32pipe, win32file, pywintypes


def pipe_server():
    print("pipe server")
    count = 0
    pipe = win32pipe.CreateNamedPipe(
        r'\\.\pipe\Foo',
        win32pipe.PIPE_ACCESS_DUPLEX,
        win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
        1, 65536, 65536,
        0,
        None)
    try:
        print("waiting for client")
        win32pipe.ConnectNamedPipe(pipe, None)
        print("got client")

        while count < 10:
            print(f"writing message {count}")
            # convert to bytes
            some_data = str.encode(f"{count}")
            win32file.WriteFile(pipe, some_data)
            time.sleep(1)
            count += 1

        print("finished now")
    finally:
        win32file.CloseHandle(pipe)


def pipe_client():
    print("pipe client")
    quit = False

    while not quit:
        try:
            handle = win32file.CreateFile(
                r'\\.\pipe\Foo',
                win32file.GENERIC_READ | win32file.GENERIC_WRITE,
                0,
                None,
                win32file.OPEN_EXISTING,
                0,
                None
            )
            res = win32pipe.SetNamedPipeHandleState(handle, win32pipe.PIPE_READMODE_MESSAGE, None, None)
            if res == 0:
                print(f"SetNamedPipeHandleState return code: {res}")
            while True:
                resp = win32file.ReadFile(handle, 64*1024)
                print(f"message: {resp}")
        except pywintypes.error as e:
            if e.args[0] == 2:
                print("no pipe, trying again in a sec")
                time.sleep(1)
            elif e.args[0] == 109:
                print("broken pipe, bye bye")
                quit = True


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("need s or c as argument")
    elif sys.argv[1] == "s":
        pipe_server()
    elif sys.argv[1] == "c":
        pipe_client()
    else:
        print(f"no can do: {sys.argv[1]}")

示例输出客户端

> python pipe_test.py c
pipe client
no pipe, trying again in a sec
no pipe, trying again in a sec
no pipe, trying again in a sec
message: (0, b'0')
message: (0, b'1')
message: (0, b'2')
message: (0, b'3')
message: (0, b'4')
message: (0, b'5')
message: (0, b'6')
message: (0, b'7')
message: (0, b'8')
message: (0, b'9')
broken pipe, bye bye

示例输出服务器

> python pipe_test.py s
pipe server
waiting for client
got client
writing message 0
writing message 1
writing message 2
writing message 3
writing message 4
writing message 5
writing message 6
writing message 7
writing message 8
writing message 9
finished now

显然,您需要对各种调用进行一些错误检查,但这应该可以工作.

Obviously you'd need some error checking around the various calls but that should work.

其他说明:我的一位同事在客户尝试对其执行I/O时就关闭了管道,但遇到麻烦(例外是声称所有管道实例都在忙").原来,他在客户端代码中使用os.path.exists来测试命名管道是否已经存在,然后在其上运行CreateFile.这莫名其妙地打破了管道.因此,使用上述方法(将CreateFile包裹在try-except中)是一种尝试连接到管道的安全方法,直到服务器端创建了管道为止.

Additional side note: A colleague of mine ran into trouble with the pipe being closed the moment the client tried to perform I/O on it (exception claiming that "all pipe instances are busy"). It turned out that he was using os.path.exists in the client code to test whether the named pipe already existed before running CreateFile on it. This somehow breaks the pipe. So using the approach above (CreateFile wrapped in a try-except) is the safe way of trying to connect to a pipe until it has been created by the server end.

这篇关于Python和Windows命名管道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆