-
Notifications
You must be signed in to change notification settings - Fork 43
Enhance OCR script: dual output (Markdown & Word) and better batch handling #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
hmdqr
wants to merge
3
commits into
Pythonation:main
Choose a base branch
from
hmdqr:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,18 +1,23 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Standard library imports | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import sys | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import base64 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import csv | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import logging | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import sqlite3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Third-party imports | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from mistralai import Mistral | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import pypandoc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from dotenv import load_dotenv | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| load_dotenv() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Load environment variables | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| load_dotenv() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Configuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DOC_DIR = "docs_import" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| EXPORT_DIR = "docs_exports" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DB_CSV = "processed_files.csv" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DB_FILE = "processed_files.db" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LOG_FILE = "conversion.log" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MAX_RETRIES = 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| INITIAL_BACKOFF = 1 # in seconds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -21,7 +26,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logging.basicConfig( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| filename=LOG_FILE, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| level=logging.INFO, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| format='%(asctime)s %(levelname)s: %(message)s', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| format="%(asctime)s %(levelname)s: %(message)s", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Ensure API key is set via environment variable | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -32,66 +37,101 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client = Mistral(api_key=API_KEY) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FIELDNAMES = ['filename', 'status', 'attempts', 'error'] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def ensure_export_directory(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Ensure the export directory exists.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not os.path.exists(EXPORT_DIR): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| os.makedirs(EXPORT_DIR) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(f"Created export directory: {EXPORT_DIR}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def init_database(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Initialize the SQLite database and create table if it doesn't exist.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn = sqlite3.connect(DB_FILE) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cursor = conn.cursor() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cursor.execute(''' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CREATE TABLE IF NOT EXISTS processed_files ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| filename TEXT PRIMARY KEY, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| status TEXT NOT NULL, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| attempts INTEGER NOT NULL, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| error TEXT, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ''') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn.commit() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn.close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def load_processed(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Load processed file records from CSV into a dict.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Load processed file records from SQLite database into a dict.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| init_database() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processed = {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if os.path.exists(DB_CSV): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with open(DB_CSV, newline='', encoding='utf-8') as csvfile: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reader = csv.DictReader(csvfile) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for row in reader: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processed[row['filename']] = row | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn = sqlite3.connect(DB_FILE) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cursor = conn.cursor() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cursor.execute('SELECT filename, status, attempts, error FROM processed_files') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for row in cursor.fetchall(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| filename, status, attempts, error = row | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processed[filename] = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'filename': filename, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'status': status, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'attempts': str(attempts), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'error': error or '' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn.close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return processed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def append_to_db(record): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Append a processing record to the CSV database.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file_exists = os.path.exists(DB_CSV) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with open(DB_CSV, 'a', newline='', encoding='utf-8') as csvfile: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| writer = csv.DictWriter(csvfile, fieldnames=FIELDNAMES) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not file_exists: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| writer.writeheader() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| writer.writerow(record) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def update_db(record): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Update or insert a processing record into the SQLite database.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| init_database() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn = sqlite3.connect(DB_FILE) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cursor = conn.cursor() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Use INSERT OR REPLACE for atomic upsert operation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cursor.execute(''' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| INSERT OR REPLACE INTO processed_files (filename, status, attempts, error) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VALUES (?, ?, ?, ?) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ''', (record['filename'], record['status'], int(record['attempts']), record['error'])) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn.commit() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn.close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def ensure_export_directory(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Ensure the export directory exists.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not os.path.exists(EXPORT_DIR): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| os.makedirs(EXPORT_DIR) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(f"Created export directory: {EXPORT_DIR}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_pdf_files(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """List all PDF files in the DOC_DIR folder and its subdirectories.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not os.path.isdir(DOC_DIR): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(f"Error: Directory '{DOC_DIR}' not found.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| os.makedirs(DOC_DIR) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Directory '{DOC_DIR}' was not found, so I created it for you. Please put your PDF files inside and run again." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sys.exit(1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pdf_files = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for root, dirs, files in os.walk(DOC_DIR): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for file in files: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if file.lower().endswith('.pdf'): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Get relative path from DOC_DIR | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if file.lower().endswith(".pdf"): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rel_path = os.path.relpath(os.path.join(root, file), DOC_DIR) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pdf_files.append(rel_path) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return pdf_files | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def encode_pdf(pdf_path): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Encode the PDF file to a base64 string.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with open(pdf_path, "rb") as pdf_file: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return base64.b64encode(pdf_file.read()).decode('utf-8') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return base64.b64encode(pdf_file.read()).decode("utf-8") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logging.error(f"Failed to encode {pdf_path}: {e}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def convert_pdf_to_markdown(pdf_filename): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Perform OCR on the PDF and write the output as a markdown file in the export directory.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Perform OCR on the PDF, save as Markdown, and convert to Word safely.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| full_path = os.path.join(DOC_DIR, pdf_filename) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b64 = encode_pdf(full_path) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not b64: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -102,39 +142,51 @@ def convert_pdf_to_markdown(pdf_filename): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model="mistral-ocr-latest", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document={ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "type": "document_url", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "document_url": f"data:application/pdf;base64,{b64}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "document_url": f"data:application/pdf;base64,{b64}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include_image_base64=False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include_image_base64=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Create output directory structure | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| output_name = pdf_filename.rsplit('.', 1)[0] + '.md' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Markdown output | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| output_name = pdf_filename.rsplit(".", 1)[0] + ".md" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| output_path = os.path.join(EXPORT_DIR, output_name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Ensure the output directory exists | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| output_dir = os.path.dirname(output_path) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if output_dir and not os.path.exists(output_dir): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| os.makedirs(output_dir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with open(output_path, 'w', encoding='utf-8') as md_file: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with open(output_path, "w", encoding="utf-8") as md_file: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for page in response.pages: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| md_file.write(f"## Page {page.index + 1}\n\n") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| md_file.write(page.markdown + "\n\n") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(f"Saved markdown file: {output_path}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if os.path.exists(output_path): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| docx_path = os.path.join( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| EXPORT_DIR, pdf_filename.rsplit(".", 1)[0] + ".docx" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pypandoc.convert_file(output_path, "docx", outputfile=docx_path) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(f"Converted to Word: {docx_path}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logging.error(f"Word conversion failed for {pdf_filename}: {e}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(f"Word conversion failed for {pdf_filename}: {e}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(f"Markdown file not found, skipping Word conversion for {pdf_filename}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+164
to
+175
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if os.path.exists(output_path): | |
| try: | |
| docx_path = os.path.join( | |
| EXPORT_DIR, pdf_filename.rsplit(".", 1)[0] + ".docx" | |
| ) | |
| pypandoc.convert_file(output_path, "docx", outputfile=docx_path) | |
| print(f"Converted to Word: {docx_path}") | |
| except Exception as e: | |
| logging.error(f"Word conversion failed for {pdf_filename}: {e}") | |
| print(f"Word conversion failed for {pdf_filename}: {e}") | |
| else: | |
| print(f"Markdown file not found, skipping Word conversion for {pdf_filename}") | |
| if os.path.exists(output_path): | |
| try: | |
| docx_path = os.path.join( | |
| EXPORT_DIR, pdf_filename.rsplit(".", 1)[0] + ".docx" | |
| ) | |
| pypandoc.convert_file(output_path, "docx", outputfile=docx_path) | |
| print(f"Converted to Word: {docx_path}") | |
| except RuntimeError as e: | |
| logging.error(f"Pandoc not found or failed for {pdf_filename}: {e}") | |
| print(f"Word conversion failed for {pdf_filename}: {e}\nPlease ensure that Pandoc is installed and available in your PATH. See https://pandoc.org/installing.html") | |
| except Exception as e: | |
| logging.error(f"Word conversion failed for {pdf_filename}: {e}") | |
| print(f"Word conversion failed for {pdf_filename}: {e}") | |
| else: | |
| print(f"Markdown file not found, skipping Word conversion for {pdf_filename}") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating the directory and then immediately exiting prevents the user from adding files and running again in the same execution. Consider checking if the directory is empty instead of just checking if it exists, or provide a way to continue execution after directory creation.