Non-blocking pipe reads in Windows Python
linux下很容易实现的方法在windows下行不通....windows下select不能操作管道
百度找了半天蛋都碎了,最后只能祭出google
感谢github!!!!看到github上的内容的时候 真是太开心了
参考来源
windows对应pipe的函数
%28v=vs.85%29.aspx
举一反三,弄了两种写法,
第一种和github的一样
第二种写法用了PeekNamedPipe
还有一种写法可以用
TransactNamedPipe,但是TransactNamedPipe要用到的一个结构体ctype.wintypes里没有封装,所以就算了
顺便linux写法也丢上去了
-
# -*- coding: UTF-8 -*-
-
__author__ = 'loliz_000'
-
-
-
import msvcrt
-
import platform
-
import time
-
from _exception import CmdException
-
-
-
def read_line_thread_unix(fileobj, switch):
-
import select
-
while 1:
-
if switch['switch']:
-
break
-
try:
-
read_list, write_list, error_list = select.select([fileobj], [], [], 0.01)
-
except OSError:
-
break
-
except IOError:
-
break
-
except select.error:
-
break
-
if len(read_list) > 0:
-
output = read_list[0].readline()
-
if not output:
-
break
-
print output
-
switch['out_line_list'].append(output)
-
-
-
def read_line_thread_windows1(fileobj, switch):
-
import time
-
from ctypes import windll, byref, GetLastError, WinError
-
# 将指定类型转化为参数类型的函数
-
from ctypes.wintypes import POINTER
-
# 载入windows handle类型
-
from ctypes.wintypes import HANDLE as HANDLE_TYPE
-
# 载入windows dword类型
-
from ctypes.wintypes import DWORD as DWORD_TYPE
-
# 载入window是bool类型
-
from ctypes.wintypes import INT as INT_TYPE
-
# DWORD类型指正
-
LPDWORD_TYPE = POINTER(DWORD_TYPE)
-
# pipe nowait参数, dword 类
-
PIPE_NOWAIT = DWORD_TYPE(0x00000001)
-
# pipe 为空时的返回码
-
ERROR_NO_DATA = 232
-
# 定位SetNamedPipeHandleState函数
-
SetNamedPipeHandleState = windll.kernel32.SetNamedPipeHandleState
-
# 确定SetNamedPipeHandleState的参数类型
-
SetNamedPipeHandleState.argtypes = [HANDLE_TYPE, LPDWORD_TYPE, LPDWORD_TYPE, LPDWORD_TYPE]
-
# 确定SetNamedPipeHandleState的返回值类型
-
SetNamedPipeHandleState.restype = INT_TYPE
-
# 管道的handle值
-
handle = msvcrt.get_osfhandle(fileobj.fileno())
-
# 设置管道非阻塞
-
res = SetNamedPipeHandleState(handle, byref(PIPE_NOWAIT), None, None)
-
# 设置结果
-
if res == 0:
-
raise CmdException('set no block pipe read catch error %s' % str(WinError()))
-
# 开始从管道读取数据
-
while 1:
-
if switch['switch']:
-
break
-
try:
-
string_buff = fileobj.readline()
-
except OSError:
-
if GetLastError() != ERROR_NO_DATA:
-
break
-
else:
-
raise CmdException('read from pipe catch error %s' % str(WinError()))
-
if len(string_buff) == 0:
-
time.sleep(0.001)
-
continue
-
else:
-
print string_buff
-
-
-
def read_line_thread_windows2(fileobj, switch):
-
from ctypes import windll, byref, GetLastError, WinError
-
# 将指定类型转化为参数类型的函数
-
from ctypes.wintypes import POINTER
-
# 载入windows handle类型
-
from ctypes.wintypes import HANDLE as HANDLE_TYPE
-
# 载入windows dword类型
-
from ctypes.wintypes import DWORD as DWORD_TYPE
-
# 载入window是bool类型
-
from ctypes.wintypes import INT as INT_TYPE
-
# LPVOID_TYPE指针
-
from ctypes.wintypes import LPVOID as LPVOID_TYPE
-
# DWORD类型指正
-
LPDWORD_TYPE = POINTER(DWORD_TYPE)
-
# 期望读取长度
-
BUFFER_SHOULD_BE_RES = DWORD_TYPE(4096)
-
# 实际读取长度
-
BUFFER_SIZE_RES = DWORD_TYPE(0)
-
# 实际发送长度
-
BUFFER_SIZE_SEND = DWORD_TYPE(0)
-
# pipe 为空时的返回码
-
ERROR_NO_DATA = 232
-
# 定位PeekNamedPipe函数
-
PeekNamedPipe = windll.kernel32.PeekNamedPipe
-
# 确定PeekNamedPipe的参数类型
-
PeekNamedPipe.argtypes = [HANDLE_TYPE, LPVOID_TYPE, DWORD_TYPE, LPDWORD_TYPE, LPDWORD_TYPE, LPDWORD_TYPE]
-
# 确定PeekNamedPipe的返回值类型
-
PeekNamedPipe.restype = INT_TYPE
-
# 管道的handle值
-
handle = msvcrt.get_osfhandle(fileobj.fileno())
-
# 开始从管道读取数据
-
while 1:
-
if switch['switch']:
-
break
-
# 获取管道信息
-
res = PeekNamedPipe(handle, None, BUFFER_SHOULD_BE_RES,
-
byref(BUFFER_SIZE_RES), byref(BUFFER_SIZE_SEND), None)
-
# 设置结果
-
if res == 0:
-
print 'get end!!'
-
break
-
#raise CmdException('set no block pipe read catch error %s' % str(WinError()))
-
if BUFFER_SIZE_RES.value <= 0:
-
time.sleep(0.001)
-
continue
-
else:
-
try:
-
gg = fileobj.read(BUFFER_SIZE_RES.value)
-
print gg
-
except OSError:
-
if GetLastError() != ERROR_NO_DATA:
-
break
-
else:
-
raise CmdException('read from pipe catch error %s' % str(WinError()))
-
#print gg.decode('gbk')
-
#print 'finsh'
-
-
-
if platform.system() == 'windows':
-
read_line_thread = read_line_thread_unix
-
else:
-
read_line_thread = read_line_thread_windows1
阅读(3627) | 评论(0) | 转发(0) |