You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kraken OCR在Windows下触发PermissionError: [WinError 32]错误求助

问题描述

搭建kraken OCR时,执行处理流程遇到如下错误:

PermissionError: [WinError 32] 进程无法访问文件,因为另一个进程正在使用它。

相关代码片段:

@cli.result_callback()
def process_pipeline(subcommands, input, batch_input, suffix, **args):
    """
    Helper function calling the partials returned by each subcommand and
    placing their respective outputs in temporary files.
    """
    import glob
    import tempfile

    input = list(input)
    if batch_input and suffix:
        for batch_expr in batch_input:
            for in_file in glob.glob(batch_expr, recursive=True):
                input.append((in_file, '{}{}'.format(os.path.splitext(in_file)[0], suffix)))

    for io_pair in input:
        try:
            base_image = io_pair[0]
            fc = [io_pair[0]] + [tempfile.mkstemp()[1] for cmd in subcommands[1:]] + [io_pair[1]] 
            for task, input, output in zip(subcommands, fc, fc[1:]):
                    task(base_image=base_image, input=input, output=output)
                    base_image = input
        finally:
            for f in fc[1:-1]:
                os.remove(f)

报错栈信息:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Users\nilsm\Documents\Evora\Anne\.venv\Scripts\kraken.exe\__main__.py", line 7, in <module>
  File "c:\Users\nilsm\Documents\Evora\Anne\.venv\Lib\site-packages\click\core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\nilsm\Documents\Evora\Anne\.venv\Lib\site-packages\click\core.py", line 1055, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "c:\Users\nilsm\Documents\Evora\Anne\.venv\Lib\site-packages\click\core.py", line 1689, in invoke
    return _process_result(rv)
           ^^^^^^^^^^^^^^^^^^^
  File "c:\Users\nilsm\Documents\Evora\Anne\.venv\Lib\site-packages\click\core.py", line 1626, in _process_result
    value = ctx.invoke(self._result_callback, value, **ctx.params)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\nilsm\Documents\Evora\Anne\.venv\Lib\site-packages\click\core.py", line 760, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\nilsm\Documents\Evora\Anne\.venv\Lib\site-packages\kraken\kraken.py", line 229, in process_pipeline
    os.remove(f)
PermissionError: [WinError 32] Le processus ne peut pas accéder au fichier car ce fichier est utilisé par un autre processus: 'C:\Users\nilsm\AppData\Local\Temp\tmp0y01ohqn'

该代码在Linux下可正常运行,但无法迁移环境,需修改代码适配Windows,解决文件占用无法删除的问题。

解决方案

问题根源是Windows严格的文件锁定机制:tempfile.mkstemp()会返回打开的文件句柄和路径,但原代码只取路径,未关闭句柄,导致删除时文件仍被系统占用。Linux允许删除未关闭句柄的文件,但Windows不行。

以下两种修改方式均可解决问题:

方式1:显式关闭mkstemp创建的文件句柄

修改临时文件创建逻辑,保存并关闭句柄后再使用路径:

@cli.result_callback()
def process_pipeline(subcommands, input, batch_input, suffix, **args):
    """
    Helper function calling the partials returned by each subcommand and
    placing their respective outputs in temporary files.
    """
    import glob
    import tempfile
    import os

    input = list(input)
    if batch_input and suffix:
        for batch_expr in batch_input:
            for in_file in glob.glob(batch_expr, recursive=True):
                input.append((in_file, '{}{}'.format(os.path.splitext(in_file)[0], suffix)))

    for io_pair in input:
        temp_handles = []  # 保存临时文件句柄,用于后续关闭
        try:
            base_image = io_pair[0]
            # 修改临时文件创建流程:关闭句柄后再收集路径
            temp_files = []
            for cmd in subcommands[1:]:
                fd, path = tempfile.mkstemp()
                temp_handles.append(fd)
                os.close(fd)  # 立即关闭句柄,释放文件占用
                temp_files.append(path)
            fc = [io_pair[0]] + temp_files + [io_pair[1]] 
            for task, input, output in zip(subcommands, fc, fc[1:]):
                    task(base_image=base_image, input=input, output=output)
                    base_image = input
        finally:
            # 防御性关闭所有句柄,避免遗漏
            for fd in temp_handles:
                try:
                    os.close(fd)
                except OSError:
                    pass
            # 删除临时文件
            for f in fc[1:-1]:
                try:
                    os.remove(f)
                except OSError:
                    pass

方式2:使用tempfile.NamedTemporaryFile替代mkstemp

NamedTemporaryFile更易用,设置delete=False避免自动删除,手动关闭句柄后再删除文件:

@cli.result_callback()
def process_pipeline(subcommands, input, batch_input, suffix, **args):
    """
    Helper function calling the partials returned by each subcommand and
    placing their respective outputs in temporary files.
    """
    import glob
    import tempfile
    import os

    input = list(input)
    if batch_input and suffix:
        for batch_expr in batch_input:
            for in_file in glob.glob(batch_expr, recursive=True):
                input.append((in_file, '{}{}'.format(os.path.splitext(in_file)[0], suffix)))

    for io_pair in input:
        temp_file_objs = []  # 保存临时文件对象
        try:
            base_image = io_pair[0]
            temp_paths = []
            for cmd in subcommands[1:]:
                # 创建临时文件,关闭后不自动删除
                tf = tempfile.NamedTemporaryFile(delete=False)
                temp_file_objs.append(tf)
                temp_paths.append(tf.name)
                tf.close()  # 立即关闭句柄
            fc = [io_pair[0]] + temp_paths + [io_pair[1]] 
            for task, input, output in zip(subcommands, fc, fc[1:]):
                    task(base_image=base_image, input=input, output=output)
                    base_image = input
        finally:
            # 关闭所有临时文件对象
            for tf in temp_file_objs:
                try:
                    tf.close()
                except OSError:
                    pass
            # 删除临时文件
            for f in fc[1:-1]:
                try:
                    os.remove(f)
                except OSError:
                    pass

补充说明

  • 两种方法都通过释放文件句柄解决Windows文件锁定问题,同时保留原有的流水线逻辑。
  • 加入try/except块是为了避免因文件已被意外处理而抛出额外错误,提升代码健壮性。

内容的提问来源于stack exchange,提问作者Nils

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 12:16:59