【问题标题】:Loading Temporary DLLs into Python on Win32在 Win32 上将临时 DLL 加载到 Python 中
【发布时间】:2013-03-21 23:56:18
【问题描述】:

我在各种 Python 代码库中看到的在运行时动态生成/加载 C 函数的常见习语是:

import tempfile
import shutil
from ctypes import CDLL

workdir = tempfile.mkdtemp()
try:
    # Generate and write code in workdir
    # ...
    # Compile and link into an .so/.dylib/.dll
    # ...
    lib = CDLL(path_to_lib)
finally:
    shutil.rmtree(workdir)

虽然这似乎在 *nix 系统上运行良好,但我不确定它在 Win32 上的运行情况如何。这是因为,根据我的经验,当临时目录中的 .dll 映射到进程时,无法取消链接。因此,rmtree 将失败。

我可以使用哪些选项来确保在 Win32 上尽快删除 .dll(以及它所在的目录)(以便在底层 lib 被 gc'ed 或应用程序终止时如此以免留下临时的麻烦)。

【问题讨论】:

    标签: python windows ctypes


    【解决方案1】:

    使用 Kernel32 函数 FreeLibrary 取消映射 DLL 并减少其引用计数。要获取句柄,您可以使用GetModuleHandleW,但它已经在_handle 属性中可用。

    编辑: 底层的_ctypes 模块已经提供了这个功能以及用于POSIX 的dlclose。如果出现错误,这些函数会引发 WindowsError / OSError

    >>> import os                               
    >>> from ctypes import *  
    >>> from _ctypes import FreeLibrary
    
    >>> lib = CDLL('./lib.dll')
    >>> hlib = lib._handle
    >>> del lib
    >>> FreeLibrary(hlib)
    
    >>> os.remove('./lib.dll')
    >>> os.path.exists('./lib.dll')
    False
    

    【讨论】:

    • 一般来说,人们希望在一段不确定的时间内使用lib。因此,我想知道是否可以说将目录和目录标记为删除(因此 Windows 将处理清理)。
    • @FreddieWitherden:我还没有调查过。您可以注册一个 Python atexit 函数来释放库并删除目录。
    • @FreddieWitherden 您的评论与问题不一致。此答案 (+1) 解决了您提出的问题。如果您希望系统在不再使用 DLL 时将其删除,我认为这是不可能的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    • 2013-11-19
    • 1970-01-01
    相关资源
    最近更新 更多