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
相关产品推荐
相关产品推荐

