У меня есть этот код для настройки многопроцессорности:
Код: Выделить всё
def process_theme_files(theme_dir: Path, processed_files: Optional[Set[str]] = None, theme_processed_files: Optional[Set[str]] = None) -> Tuple[List[Tuple[str, int, str, str, str, str, str, str]], List[Exception]]:
"""
Processes files of a specific theme in a multiprocessed manner.
Parameters:
- theme_dir (Path): Path object pointing to the theme directory.
- processed_files (set, optional): Set of globally processed files. Defaults to None.
- theme_processed_files (set, optional): Set of files processed in the current theme. Defaults to None.
Returns:
- Tuple[List[Tuple[str, int, str, str, str, str, str, str]], List[Exception]]: A tuple containing a list of tuples
containing extracted information from the theme files and a list of exceptions encountered during the processing.
"""
results = []
exceptions = []
# Number of processes to be used (can be adjusted as needed)
num_processes = multiprocessing.cpu_count()
# Initialize processed_files and theme_processed_files as empty sets if not provided
if processed_files is None:
processed_files = set()
if theme_processed_files is None:
theme_processed_files = set()
# Get PDF files in the theme directory
pdf_files = list(theme_dir.glob('**/*.pdf'))
# Create progress bar
with tqdm(total=len(pdf_files), desc='Processing PDFs', unit='file') as pbar:
# Process PDF files in parallel using ProcessPoolExecutor
with concurrent.futures.ProcessPoolExecutor(max_workers=num_processes) as executor:
# Map the process_file function to each PDF file in the list
future_to_file = {executor.submit(process_file, pdf_file): pdf_file for pdf_file in pdf_files}
# Iterate over results as they become available
for future in concurrent.futures.as_completed(future_to_file):
pdf_file = future_to_file[future]
try:
# Get the result of the task
file_results, file_exceptions = future.result()
# Extend the results list
results.extend(file_results)
# Append specific exceptions to the exceptions list
exceptions.extend(file_exceptions)
except FileNotFoundError as fnfe:
exceptions.append(f"File not found: {fnfe.filename}")
except Exception as e:
# Capture and log the generic exception
exceptions.append(f"Error processing file '{pdf_file}': {e}")
# Update the progress bar
pbar.update(1)
return results, exceptions
Код: Выделить всё
def process_file(file_path: Path):
"""
Process a PDF file to extract text and information.
Args:
- file_path (Path): Path object representing the location of the PDF file.
Returns:
- Tuple[List, List]: A tuple containing two lists:
1. List of extracted results.
2. List of encountered exceptions during processing.
Raises:
- FileNotFoundError: If the specified file_path does not exist.
- Exception: For any other unexpected errors during processing.
"""
results = [] # List to store extracted information from each page
exceptions = [] # List to store exceptions encountered during processing
try:
# Check the size of the PDF file
pdf_size_bytes = os.path.getsize(file_path)
pdf_size_mb = pdf_size_bytes / (1024 * 1024)
# Check if the PDF file size exceeds the maximum allowed size
if pdf_size_mb > MAX_PDF_SIZE_MB:
exceptions.append((file_path, f"The file exceeds the maximum allowed size of {MAX_PDF_SIZE_MB} MB."))
print(f'{file_path} - Exceeds maximum allowed size of {MAX_PDF_SIZE_MB} MB.')
return results, exceptions
# Open the PDF file and read its content into a BytesIO buffer
with file_path.open('rb') as file:
pdf_data_buffer = BytesIO(file.read())
# Iterate through each page of the PDF
for page_number, page in enumerate(PDFPage.get_pages(pdf_data_buffer, check_extractable=True)):
# Extract text from the current page
page_text = extract_text(pdf_data_buffer, page_numbers=[page_number])
# Process the extracted text to extract information
page_results, page_exceptions = extract_information(page_text, file_path.name, page_number + 1) # Page numbers are 1-based
# Extend results and exceptions lists with page-specific results and exceptions
results.extend(page_results)
exceptions.extend(page_exceptions)
except FileNotFoundError as e:
# Handle case where the file does not exist
exceptions.append(e)
print(f"FileNotFoundError: {e}")
raise
except Exception as e:
# Handle any other unexpected exceptions
exceptions.append(e)
print(f"Exception: {e}")
raise
return results, exceptions

Благодаря своим исследованиям я узнал, что PDF-файлы нельзя читать случайным образом; их нужно читать последовательно от начала до конца файла, как я это и реализовал.
Некоторые из моих PDF-файлов имеют размер около 100 МБ, но никогда не превышают 200 МБ, и некоторые из них довольно длинные (1000 страниц) и содержат множество изображений. Поскольку мне приходится читать все страницы при обработке PDF-файла, единственным обходным решением, которое я смог найти, было ограничение размера PDF-файлов, которые я читаю, до уровня менее 100 МБ. Я также не могу придумать, как ограничить количество страниц - потому что, чтобы определить количество страниц, мне нужно открыть и прочитать файл.
Как я могу ограничить Использование оперативной памяти в этой программе?
Подробнее здесь: https://stackoverflow.com/questions/788 ... ws-the-ram