Я сделал скрипт для пакетной обработки PDF-сканов в текст с помощью tesseract и pyocr. Код ниже. Проблема в том, что при обработке большого количества файлов, например, 20+, в какой-то момент сценарию просто не хватает памяти и происходит сбой с OSError. В настоящее время я сделал это так, чтобы он мог плавно наверстать упущенное после ручного перезапуска, но эти ручные перезапуски утомительны.
Поскольку pyocr для меня в основном черный ящик, я попытался обернуть скрипт в другие скрипты Python, которые перезапустили бы его при сбое, но все они, кажется, выходят из строя из-за этой ошибки, освобождая память только тогда, когда завершается каждый связанный скрипт.
Единственное другое решение, которое я могу придумать, - это создать полностью внешнюю оболочку, которая проверяла бы, работает ли скрипт, и перезапускала бы его, если нет, И все еще есть необработанные файлы.
Но, может быть, есть лучшее решение? Или, может быть, я сделал хромой код, который можно улучшить, чтобы избежать этих сбоев памяти? (Кроме того, что я знаю, что это хромает, но работает достаточно хорошо :)).
from io import BytesIO
from wand.image import Image
from PIL import Image as PI
import pyocr
import pyocr.builders
import io
import os
import os.path
import ast
def daemon_ocr(tool, img, lang):
txt = tool.image_to_string(
PI.open(BytesIO(img)),
lang=lang,
builder=pyocr.builders.TextBuilder()
)
return txt
def daemon_wrap(image_pdf, tool, lang, iteration):
print(iteration)
req_image = []
final_text = ''
image_pdf_bckp = image_pdf
image_jpeg = image_pdf.convert('jpeg')
for img in image_jpeg.sequence:
img_page = Image(image=img)
req_image.append(img_page.make_blob('jpeg'))
for img in req_image:
txt = daemon_ocr(tool, img, lang)
final_text += txt + '\n '
if 'работ' not in final_text and 'фактура' not in final_text and 'Аренда' not in final_text and 'Сумма' not in final_text\
and 'аренде' not in final_text and 'товара' not in final_text:
if iteration < 5:
iteration += 1
image_pdf = image_pdf.rotate(90)
final_text = daemon_wrap(image_pdf_bckp, tool, lang, iteration)
return final_text
def daemon_pyocr(food):
tool = pyocr.get_available_tools()[0]
lang = tool.get_available_languages()[0]
iteration = 1
image_pdf = Image(filename='{doc_name}'.format(doc_name=food), resolution=300)
final_text = daemon_wrap(image_pdf, tool, lang, iteration)
return final_text
files = [f for f in os.listdir('.') if os.path.isfile(f)]
output = {}
print(files)
path = os.path.dirname(os.path.abspath(__file__))
if os.path.exists('{p}/output'.format(p=path)):
text_file = open("output", "a")
first = False
else:
text_file = open("output", "w")
first = True
for f in files:
if f != 'ocr.py' and f != 'output':
try:
output[f] = daemon_pyocr(f)
print('{f} done'.format(f=f))
if first:
text_file.write(str(output)[1:-1])
first = False
else:
text_file.write(', {d}'.format(d=str(output)[1:-1]))
output = {}
os.rename('{p}/{f}'.format(p=path, f=f), "{p}/done/{f}".format(p=path, f=f))
except OSError:
print('{f} failed: not enough memory.'.format(f=f))