Python 使用ctypes创建的文件处理程序无效

Python 使用ctypes创建的文件处理程序无效,python,ctypes,Python,Ctypes,我试图用python中的ctypes创建一个新文件。文件被创建,我可以写入其中。当我尝试读取此文件时,问题开始出现。它给我一个无效的文件句柄错误。任何人都可能知道为什么会这样 以下是我使用的代码: from ctypes import * def CreateFile(file_name='',data=''): file_handler=windll.Kernel32.CreateFileA(file_name,0x10000000,0,None,4,0x80,None)

我试图用python中的
ctypes
创建一个新文件。文件被创建,我可以写入其中。当我尝试读取此文件时,问题开始出现。它给我一个无效的文件句柄错误。任何人都可能知道为什么会这样

以下是我使用的代码:

from ctypes import *

def CreateFile(file_name='',data=''):

    file_handler=windll.Kernel32.CreateFileA(file_name,0x10000000,0,None,4,0x80,None)

    pointer_to_written_data=c_int(0)
    windll.Kernel32.WriteFile(file_handler,data,len(data),byref(pointer_to_written_data),None)
    windll.Kernel32.CloseHandle(file_handler)
    return

def ReadAFile(file_name=''):

    file_handler=windll.Kernel32.CreateFileA(file_name,0x10000000,0,None,4,0x80,None)
    data=create_string_buffer(4096)
    pointer_to_read_data=c_int(0)
    if(windll.Kernel32.ReadFile(file_handler,byref(data),1024,byref(pointer_to_read_data),None)==0):
            print "Failed"
    print windll.Kernel32.GetLastError()
    windll.Kernel32.CloseHandle(file_handler)
    print data.value
    return

CreateFile("sample.txt","This is a test file!!")
ReadAFile("sample.txt")

您的代码在CloseHandle编辑后仍按原样工作

CreateFile()
中未关闭文件句柄时,在
ReadAFile
中打开文件失败,因为该文件已打开。您没有检查错误,因此对
ReadFile
的调用失败。现在,代码被编辑为在
CreateFile
中具有
CloseHandle
,它就可以工作了。注意,您可能需要关闭并重新打开IDE,因为它可能会保持文件的句柄打开,直到您终止该进程,因为它是一个句柄泄漏(我有这个问题)

我还发现,在ctypes中,显式定义
argtypes
restype
errcheck
非常有用<代码>错误检查尤其如此,因为代码将抛出错误,并且您不必检查返回值是否失败

from ctypes import *
from ctypes import wintypes as w

INVALID_HANDLE_VALUE = w.HANDLE(-1).value
GENERIC_ALL = 0x10000000
OPEN_ALWAYS = 4
FILE_ATTRIBUTE_NORMAL = 0x80

_k32 = WinDLL('kernel32',use_last_error=True)
_CreateFileA = _k32.CreateFileA
_WriteFile = _k32.WriteFile
_ReadFile = _k32.ReadFile
_CloseHandle = _k32.CloseHandle

def validate_handle(result,func,args):
    if result == INVALID_HANDLE_VALUE:
        raise WindowsError(get_last_error())
    return result

def validate_bool(result,func,args):
    if not result:
        raise WindowsError(get_last_error())

_CreateFileA.argtypes = w.LPCSTR,w.DWORD,w.DWORD,c_void_p,w.DWORD,w.DWORD,w.HANDLE
_CreateFileA.restype = w.HANDLE
_CreateFileA.errcheck = validate_handle
_WriteFile.argtypes = w.HANDLE,c_void_p,w.DWORD,POINTER(w.DWORD),c_void_p
_WriteFile.restype = w.BOOL
_WriteFile.errcheck = validate_bool
_ReadFile.argtypes = w.HANDLE,w.LPVOID,w.DWORD,POINTER(w.DWORD),c_void_p
_ReadFile.restype = w.BOOL
_ReadFile.errcheck = validate_bool
_CloseHandle.argtypes = w.HANDLE,
_CloseHandle.restype = w.BOOL
_CloseHandle.errcheck = validate_bool

def CreateFile(file_name='',data=''):
    file_handler = _CreateFileA(file_name,GENERIC_ALL,0,None,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,None)
    written = w.DWORD()
    try:
        _WriteFile(file_handler,data,len(data),byref(written),None)
    finally:
        _CloseHandle(file_handler)

def ReadAFile(file_name=''):
    file_handler = _CreateFileA(file_name,GENERIC_ALL,0,None,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,None)
    data = create_string_buffer(4096)
    read = w.DWORD()
    try:
        _ReadFile(file_handler,byref(data),1024,byref(read),None)
    finally:
        _CloseHandle(file_handler)
    print data.value

CreateFile("sample.txt","This is a test file!!")
ReadAFile("sample.txt")

您的代码在CloseHandle编辑后仍按原样工作

CreateFile()
中未关闭文件句柄时,在
ReadAFile
中打开文件失败,因为该文件已打开。您没有检查错误,因此对
ReadFile
的调用失败。现在,代码被编辑为在
CreateFile
中具有
CloseHandle
,它就可以工作了。注意,您可能需要关闭并重新打开IDE,因为它可能会保持文件的句柄打开,直到您终止该进程,因为它是一个句柄泄漏(我有这个问题)

我还发现,在ctypes中,显式定义
argtypes
restype
errcheck
非常有用<代码>错误检查尤其如此,因为代码将抛出错误,并且您不必检查返回值是否失败

from ctypes import *
from ctypes import wintypes as w

INVALID_HANDLE_VALUE = w.HANDLE(-1).value
GENERIC_ALL = 0x10000000
OPEN_ALWAYS = 4
FILE_ATTRIBUTE_NORMAL = 0x80

_k32 = WinDLL('kernel32',use_last_error=True)
_CreateFileA = _k32.CreateFileA
_WriteFile = _k32.WriteFile
_ReadFile = _k32.ReadFile
_CloseHandle = _k32.CloseHandle

def validate_handle(result,func,args):
    if result == INVALID_HANDLE_VALUE:
        raise WindowsError(get_last_error())
    return result

def validate_bool(result,func,args):
    if not result:
        raise WindowsError(get_last_error())

_CreateFileA.argtypes = w.LPCSTR,w.DWORD,w.DWORD,c_void_p,w.DWORD,w.DWORD,w.HANDLE
_CreateFileA.restype = w.HANDLE
_CreateFileA.errcheck = validate_handle
_WriteFile.argtypes = w.HANDLE,c_void_p,w.DWORD,POINTER(w.DWORD),c_void_p
_WriteFile.restype = w.BOOL
_WriteFile.errcheck = validate_bool
_ReadFile.argtypes = w.HANDLE,w.LPVOID,w.DWORD,POINTER(w.DWORD),c_void_p
_ReadFile.restype = w.BOOL
_ReadFile.errcheck = validate_bool
_CloseHandle.argtypes = w.HANDLE,
_CloseHandle.restype = w.BOOL
_CloseHandle.errcheck = validate_bool

def CreateFile(file_name='',data=''):
    file_handler = _CreateFileA(file_name,GENERIC_ALL,0,None,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,None)
    written = w.DWORD()
    try:
        _WriteFile(file_handler,data,len(data),byref(written),None)
    finally:
        _CloseHandle(file_handler)

def ReadAFile(file_name=''):
    file_handler = _CreateFileA(file_name,GENERIC_ALL,0,None,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,None)
    data = create_string_buffer(4096)
    read = w.DWORD()
    try:
        _ReadFile(file_handler,byref(data),1024,byref(read),None)
    finally:
        _CloseHandle(file_handler)
    print data.value

CreateFile("sample.txt","This is a test file!!")
ReadAFile("sample.txt")


为什么你要使用ctypes来读/写文件?只是学习如何在python中使用ctypes作为课程的一部分。你应该在写完文件后调用
CloseHandle
。嘿@ekhumoro我在写完文件后尝试过了,结果是你可以读取一个没有使用ctypes创建的文件了吗?你为什么要使用ctypes来读呢读/写文件?只是学习如何在python中使用ctypes作为课程的一部分。在编写文件后,你应该调用
CloseHandle
。嘿@ekhumoro,我在写入文件后尝试过了,结果是你可以读取一个没有使用ctypes创建的文件吗?谢谢标记!!当我将函数CreateFile和ReadFile作为两个独立的程序运行时,该程序可以工作。当我试图关闭CreateFile实例中的文件处理程序时,它会给我一个无效的处理程序错误,这似乎也会影响下一个函数。发生这种情况的原因是什么?@kvnbni正如我提到的,如果您在IDE中运行这些脚本并且出现故障,则可能会导致句柄泄漏。我提供的代码检查错误并已尝试/最终,因此如果读/写时出错,句柄仍将关闭。正确设置
argtypes
restype
也很重要。在64位系统上,默认返回值是32位int,句柄是64位的。有什么资源可以让我进一步了解这一点吗。谢谢你的帮助。真的很感激!!考虑使用<代码> CreateFileW <代码> >代码> LPCWSTR ,而不是<代码> CuraMeLea<代码>。在本例中,Python 2 ctypes会自动解码作为参数传递的字节字符串。它的默认转换是
('mbcs','ignore')
,但我建议通过
ctypes切换到严格的错误处理。设置转换模式('mbcs','strict')
(仅限2.x)。在Windows中,文件路径应该是Unicode的,但Python2对此需要一些规范。如果可以,请升级到3.6。此外,不要打开具有
GENERIC\u ALL
访问权限的文件来读取它。使用
GENERIC\u READ
。在这种情况下,您甚至可以使用
FILE\u READ\u DATA
(1),其中
CreateFile
将自动添加所需的最低访问权限:
SYNCHRONIZE
FILE\u READ\u ATTRIBUTES
。谢谢!!当我将函数CreateFile和ReadFile作为两个独立的程序运行时,该程序可以工作。当我试图关闭CreateFile实例中的文件处理程序时,它会给我一个无效的处理程序错误,这似乎也会影响下一个函数。发生这种情况的原因是什么?@kvnbni正如我提到的,如果您在IDE中运行这些脚本并且出现故障,则可能会导致句柄泄漏。我提供的代码检查错误并已尝试/最终,因此如果读/写时出错,句柄仍将关闭。正确设置
argtypes
restype
也很重要。在64位系统上,默认返回值是32位int,句柄是64位的。有什么资源可以让我进一步了解这一点吗。谢谢你的帮助。真的很感激!!考虑使用<代码> CreateFileW <代码> >代码> LPCWSTR ,而不是<代码> CuraMeLea<代码>。在本例中,Python 2 ctypes会自动解码作为参数传递的字节字符串。它的默认转换是
('mbcs','ignore')
,但我建议通过
ctypes切换到严格的错误处理。设置转换模式('mbcs','strict')
(仅限2.x)。在Windows中,文件路径应该是Unicode的,但Python2对此需要一些规范。如果可以,请升级到3.6。此外,不要打开具有
GENERIC\u ALL
访问权限的文件来读取它。使用
GENERIC\u READ
。在这种情况下,您甚至可以使用
FILE\u READ\u DATA
(1),
CreateFile
将自动向其中添加所需的最低访问权限:
SYNCHRONIZE
FILE\u READ\u ATTRIBUTES