Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python 3.7中使用和重叠命名管道_Python_Pipe_Named Pipes_Overlapped Io - Fatal编程技术网

在Python 3.7中使用和重叠命名管道

在Python 3.7中使用和重叠命名管道,python,pipe,named-pipes,overlapped-io,Python,Pipe,Named Pipes,Overlapped Io,我将Windows与Python3.7一起使用,并尝试在Python进程之间异步共享数据(仅字符串)。其中一个正在无限期运行(receiver),另一个可能在任何点开始发送一些数据,然后结束(sender)。我正在尝试使用一个命名的管道 当它们同步运行时(接收器在阻塞的管道上等待,直到获得数据),我成功地得到了这个结果,但是接收器还有其他事情要做,理想情况下,他不应该一直等待。另外,在某个时候可能会有第二个发送器,所以阻塞的管道不是很好 接收器的代码为: import os import tim

我将Windows与Python3.7一起使用,并尝试在Python进程之间异步共享数据(仅字符串)。其中一个正在无限期运行(receiver),另一个可能在任何点开始发送一些数据,然后结束(sender)。我正在尝试使用一个命名的管道

当它们同步运行时(接收器在阻塞的管道上等待,直到获得数据),我成功地得到了这个结果,但是接收器还有其他事情要做,理想情况下,他不应该一直等待。另外,在某个时候可能会有第二个发送器,所以阻塞的管道不是很好

接收器的代码为:

import os
import time
import sys
import win32pipe, win32file, pywintypes

pipe_name = r'\\.\pipe\mypipe' 

pipe = win32pipe.CreateNamedPipe(
        pipe_name,
        win32pipe.PIPE_ACCESS_DUPLEX | win32file.FILE_FLAG_OVERLAPPED,  # open mode 
        win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT, # pipe mode
        1, 65536, 65536, # max instances, out buffer size,  in buffer size
        0, # timeout
    None)


while 1:
    print("doing my other stuff")
    try:
        win32pipe.ConnectNamedPipe(pipe, pywintypes.OVERLAPPED())
    except pywintypes.error as e:
        if e.winerror == 232:   #disconnected pipe
            win32pipe.DisconnectNamedPipe(pipe)
            print("Disconnecting pipe")
        else:
            print(e)
    try:
        retval, msg = win32file.ReadFile(pipe, 0, pywintypes.OVERLAPPED())
        print(msg)
    except pywintypes.error as e:
        if e.winerror == 536: #Wating for connection
            print("waiting")
        elif e.winerror == 233: #no process on other side
            continue
    time.sleep(1)
发件人的代码为:

import os
import time
import sys
import win32pipe, win32file, pywintypes


pipe_name = r'\\.\pipe\mypipe' 


for x in range(5):

    handle = win32file.CreateFile(
            pipe_name,
            win32file.GENERIC_READ | win32file.GENERIC_WRITE,
            0,
            None,
            win32file.OPEN_EXISTING,
            win32file.FILE_FLAG_OVERLAPPED,
            None
            )
    res = win32pipe.SetNamedPipeHandleState(handle, win32pipe.PIPE_READMODE_MESSAGE, None, None)
    print(f"sending {x}")
    win32file.WriteFile(handle, str.encode(f"hello world {x}"))
    win32file.CloseHandle(handle)
    time.sleep(2)
现在两者都可以运行并有一些连接,但我无法真正获得数据。如果发送了内容,接收器可以执行其他操作,断开并重新打开管道,但
msg
最终为空。如果我在调试器中停止它并发送一些东西,
msg
的值会得到“0x0处的内存……”,我会将其解释为某种指针,但您可能已经注意到,我对管道的理解是有限的

我找到了一个很好的synchronos管道的例子。我把管道的制作改成了接受器,但这并不难。我找到了一些异步(重叠)管道的例子,这些例子也很棒,但给我留下了我现在面临的问题

从重叠的管道中读取仍然是
win32file.ReadFile
的任务,还是我缺少了其他的东西


多谢各位

我找到了解决方案并想与大家分享,以防其他人在这个问题上结结巴巴。事实证明,
msg
获取“0x0处的内存……”是一个对象,其数据可以通过
bytes(msg)
公开

我的
ReadFile
命令也有问题,因为缓冲区必须>0才能实现任何功能。现在它逐个读取每个字节,并将它们相加为一个字符串。这在性能上可能不是很好,但对我来说是可行的,它解决了在消息长度小于缓冲区长度时必须缩短结尾的问题

msg = ''
rtnvalue, data = win32file.ReadFile(pipe, 1, pywintypes.OVERLAPPED())
while rtnvalue == 234:
    msg = msg + bytes(data).decode('ASCII') 
    rtnvalue, data = win32file.ReadFile(pipe, 1, pywintypes.OVERLAPPED())
if rtnvalue == 0: #end of stream is reached
    msg = msg + bytes(data).decode('ASCII')
return msg

海报的代码和接受的答案不处理待处理的错误。不幸的是,我在其他地方找不到一个好的Python示例,所以我花了一些时间来解决它

为您的环境进行修改,连接到管道服务器,然后调用receive()。它将从管道返回完整消息,或不返回任何消息

如果要查看代码的工作方式,请将read_buf的大小设置为较低的值,例如64字节,并添加一些日志记录语句

对于文件和套接字,相同的代码应该同样有效(通过lite修改)


import win32file
import win32pipe
import winerror
import pywintypes

class pipe_comms:
    def __init__(self):
        self.pipe_open = False
        self.pipe_handle = None
        self.pipe_name = r”\\.\pipe\your_pipe”
        self.read_msg = None
        self.overlapped = None
        self.read_buf = win32file.AllocateReadBuffer(4096)

    def connect(self):
        if not self.pipe_open:
            try:
                self.pipe_handle = win32file.CreateFile(self.pipe_name
                    win32file.GENERIC_READ | win32file.GENERIC_WRITE,
                    0, None, win32file.OPEN_EXISTING,
                    win32file.FILE_FLAG_OVERLAPPED, None)
                win32pipe.SetNamedPipeHandleState(self.pipe_handle, 
                    win32pipe.PIPE_READMODE_MESSAGE, None, None)
                self.pipe_open = True
                self.read_msg = None
            except pywintypes.error as e:
                self.handle_error(e.args[0])
                return False
        return True

    def receive(self):
        try:
            result = self.receive_overlapped()
            if result == winerror.ERROR_SUCCESS:
                fullMsg = self.read_msg
                self.read_msg = None
                return fullMsg
            elif result == winerror.ERROR_IO_PENDING:
                return None
            else:
                self.handle_error(result)
        except pywintypes.error as e:
            self.handle_error(e.args[0])
            return None

    def receive_overlapped(self):
        if self.overlapped:
            try:
                bytes_read = win32file.GetOverlappedResult(self.pipe_handle, self.overlapped, 0)
                self.read_msg += bytes(self.read_buf[:bytes_read])
                self.overlapped = None
                return winerror.ERROR_SUCCESS
            except pywintypes.error as e:
                result = e.args[0]
                if result = winerror.ERROR_MORE_DATA:
                    bytes_read = len(self.read_buf)
                    self.read_msg += bytes(self.read_buf[:bytes_read])
                    # fall thru to issue new ReadFile
                else:
                    # ERROR_IO_PENDING is normal, anything else is not
                    return result 
        else:
            self.read_msg = bytes()
            self.overlapped = pywintypes.OVERLAPPED()

        result, data = win32file.ReadFile(self.pipe_handle, self.read_buf, self.overlapped)
        while True:
            if result = winerror.ERROR_MORE_DATA:
                bytes_read = len(pipe_data)
                self.read_msg = bytes(data[:bytes_read])
                result, data = win32file.ReadFile(self.pipe_handle, self.read_buf, self.overlapped)
                continue
            elif result == winerror.ERROR_SUCCESS:
                bytes_read = win32file.GetOverlappedResult(self.pipe_handle, self.overlapped, 0)
                self.read_msg = bytes(data[:bytes_read])
                self.overlapped = None
            return result

    def handle_error(self, result):
        reset_pipe = False
        if result == winerror.ERROR_BROKEN_PIPE:
            win32pipe.DisconnectNamedPipe(self.pipe_handle)
            reset_pipe = True
        elif result == winerror.ERROR_NO_DATA:
            reset_pipe = True
            
        if reset_pipe:
            self.pipe_handle = None
            self.pipe_open = False
            self.read_msg = None
            self.overlapped = None
        

当管道中出现某些东西时,是否希望接收器立即中断其其他任务-放下所有东西并提供新信息?不,如果它只是在下一个循环中做出反应就足够了