杰瑞科技汇

python调用creatfile

  1. 使用 ctypes 库(推荐,无需安装第三方库)ctypes 是 Python 的标准库,允许您直接调用 DLL 中的函数,这是最基础、最灵活的方法。
  2. 使用 pywin32 库(功能更强大,需要安装)pywin32 是一个第三方库,它为 Windows API 提供了更 Pythonic 的封装,使用起来可能更方便,尤其是在处理 COM 对象和复杂结构时。

下面我将详细介绍这两种方法,并提供完整的代码示例。

python调用creatfile-图1
(图片来源网络,侵删)

使用 ctypes 库(标准库)

这是最直接的方法,我们不需要安装任何额外的包。

步骤 1:导入 ctypes 并定义函数

CreateFile 函数位于 kernel32.dll 中,我们需要告诉 Python 这个函数的原型(参数类型和返回值类型)。

import ctypes
from ctypes import wintypes
# 加载 kernel32.dll
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
# 定义 CreateFile 函数的参数和返回值类型
# Windows API 文档: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
kernel32.CreateFileW.argtypes = [
    wintypes.LPCWSTR,  # lpFileName
    wintypes.DWORD,    # dwDesiredAccess
    wintypes.DWORD,    # dwShareMode
    wintypes.LPVOID,   # lpSecurityAttributes
    wintypes.DWORD,    # dwCreationDisposition
    wintypes.DWORD,    # dwFlagsAndAttributes
    wintypes.HANDLE    # hTemplateFile
]
kernel32.CreateFileW.restype = wintypes.HANDLE  # 返回一个句柄 (HANDLE)

重要提示

  • 我们使用 CreateFileW 而不是 CreateFileAW 版本表示 "Wide",使用 Unicode (UTF-16) 字符串,可以更好地处理非英文字符。A 版本使用 ANSI 字符串。
  • argtypes 定义了每个参数的类型。
  • restype 定义了函数返回值的类型。CreateFile 返回一个 HANDLE(句柄),在 ctypes 中通常用 wintypes.HANDLE 表示,它本质上是一个无符号整数。

步骤 2:定义常量

CreateFile 的参数中有多个标志位常量,我们需要从 Windows API 中导入它们。

python调用creatfile-图2
(图片来源网络,侵删)
# --- 常量定义 ---
# Desired Access (dwDesiredAccess)
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
GENERIC_EXECUTE = 0x20000000
GENERIC_ALL = 0x10000000
# Share Mode (dwShareMode)
FILE_SHARE_READ = 0x00000001
FILE_SHARE_WRITE = 0x00000002
FILE_SHARE_DELETE = 0x00000004
# Creation Disposition (dwCreationDisposition)
CREATE_NEW = 1
CREATE_ALWAYS = 2
OPEN_EXISTING = 3
OPEN_ALWAYS = 4
TRUNCATE_EXISTING = 5
# Flags and Attributes (dwFlagsAndAttributes)
FILE_ATTRIBUTE_NORMAL = 0x80
FILE_FLAG_OVERLAPPED = 0x40000000

步骤 3:调用函数并处理结果

现在我们可以调用 CreateFile 来创建或打开一个文件。

def create_file_with_ctypes(file_path):
    """
    使用 ctypes 调用 CreateFile 创建或打开文件。
    """
    # 打开一个已存在的文件进行读写
    # 如果文件不存在,会失败
    handle = kernel32.CreateFileW(
        file_path,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ,  # 允许其他进程读取
        None,             # 默认安全属性
        OPEN_EXISTING,   # 必须已存在
        FILE_ATTRIBUTE_NORMAL,
        None              # 无模板文件
    )
    # 检查调用是否成功
    if handle == wintypes.HANDLE(-1).value:  # INVALID_HANDLE_VALUE
        error_code = ctypes.get_last_error()
        print(f"创建文件失败!错误代码: {error_code}")
        # 可以使用 FormatMessage 获取错误信息的文本描述
        return None
    else:
        print(f"文件打开成功!句柄: {handle}")
        # 使用完毕后,必须关闭句柄!
        kernel32.CloseHandle(handle)
        return handle
# --- 示例用法 ---
if __name__ == "__main__":
    # 假设我们有一个 test.txt 文件
    file_to_open = "C:\\temp\\test.txt"
    # 如果文件不存在,先创建一个
    import os
    os.makedirs("C:\\temp", exist_ok=True)
    with open(file_to_open, "w") as f:
        f.write("Hello, CreateFile!")
    print("--- 尝试打开一个已存在的文件 ---")
    create_file_with_ctypes(file_to_open)
    print("\n--- 尝试创建一个新文件 (CREATE_ALWAYS) ---")
    new_file_path = "C:\\temp\\newfile.txt"
    handle = kernel32.CreateFileW(
        new_file_path,
        GENERIC_WRITE,
        0,  # 不共享
        None,
        CREATE_ALWAYS, # 如果存在则覆盖,不存在则创建
        FILE_ATTRIBUTE_NORMAL,
        None
    )
    if handle != wintypes.HANDLE(-1).value:
        print(f"文件创建/覆盖成功!句柄: {handle}")
        kernel32.CloseHandle(handle)
    else:
        print("文件创建失败!")
    print("\n--- 尝试打开一个不存在的文件 (OPEN_EXISTING) ---")
    non_existent_file = "C:\\temp\\non_existent.txt"
    create_file_with_ctypes(non_existent_file)

使用 pywin32

pywin32 将 Windows API 的类型和函数映射到了 Python 的原生类型,使用起来更直观。

步骤 1:安装 pywin32

你需要安装这个库,打开命令行(CMD 或 PowerShell)并运行:

pip install pywin32

步骤 2:调用函数

pywin32 已经为你定义好了所有的常量和函数原型。

import win32file
import winerror
def create_file_with_pywin32(file_path):
    """
    使用 pywin32 调用 CreateFile 创建或打开文件。
    """
    # 打开一个已存在的文件进行读写
    try:
        # pywin32 的 CreateFile 直接返回句柄,如果失败会抛出异常
        handle = win32file.CreateFile(
            file_path,
            win32file.GENERIC_READ | win32file.GENERIC_WRITE,
            win32file.FILE_SHARE_READ,
            None,
            win32file.OPEN_EXISTING,
            win32file.FILE_ATTRIBUTE_NORMAL,
            None
        )
        print(f"文件打开成功!句柄: {handle}")
        # 使用完毕后,必须关闭句柄!
        win32file.CloseHandle(handle)
        return handle
    except pywintypes.error as e:
        # pywintypes.error 是一个包含 (error_code, function_name, error_message) 的元组
        print(f"创建文件失败!错误代码: {e.winerror}, 错误信息: {e.strerror}")
        return None
# --- 示例用法 ---
if __name__ == "__main__":
    import os
    file_to_open = "C:\\temp\\test.txt"
    os.makedirs("C:\\temp", exist_ok=True)
    if not os.path.exists(file_to_open):
        with open(file_to_open, "w") as f:
            f.write("Hello, pywin32!")
    print("--- 使用 pywin32 尝试打开一个已存在的文件 ---")
    create_file_with_pywin32(file_to_open)
    print("\n--- 使用 pywin32 尝试打开一个不存在的文件 ---")
    non_existent_file = "C:\\temp\\non_existent_pywin32.txt"
    create_file_with_pywin32(non_existent_file)

总结与对比

特性 ctypes (标准库) pywin32 (第三方库)
安装 无需安装,Python 自带 需要使用 pip install pywin32
易用性 较低,需要手动定义所有类型和常量 较高,常量和类型已预定义,代码更简洁
灵活性 极高,可以调用任何 DLL 中的任何函数 高,主要覆盖了常用的 Win32 API
错误处理 通过 get_last_error() 获取错误码 通过捕获 pywintypes.error 异常,信息更丰富
适用场景 简单调用、环境受限(不能安装包)、学习底层原理 快速开发、需要频繁调用 Win32 API、处理复杂 Windows 任务

推荐

  • 如果你只是想快速实现功能,或者这个脚本需要在很多不同的 Python 环境中运行,首选 pywin32
  • 如果你想了解 Python 是如何与 DLL 交互的,或者你在一个无法安装第三方包的受限环境中,使用 ctypes 是一个很好的选择。
分享:
扫描分享到社交APP
上一篇
下一篇