admin管理员组文章数量:1125579
I created a Python Flask API to convert DOCX files to PDF. It works perfectly when I start it manually via the command line. However, I’d like to turn it into a Windows service so that it can start automatically and restart if needed.
I tried using NSSM to set it up as a service, and while everything seemed to work, the service couldn't open the DOCX files no matter what I tried.
I also experimented with pywin32, but the requests completely failed once the service was started.
I don’t think this is a permissions issue. I added logging to my code and verified that the DOCX files are received correctly, have the right permissions, and are in the correct format.
Does anyone have an idea of how to resolve this?
Here is my UPDATED code :
import win32com.client
import pythoncom
import inspect, os
from flask import Flask, request, send_file
import tempfile
import logging
import time
import stat
import getpass
# Set up logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
app = Flask(__name__)
# WordHandler class to handle opening and closing Word application
class WordHandler:
def __init__(self):
self.word = None
logger.debug("WordHandler initialized")
def __enter__(self):
logger.debug("Starting Word application...")
start_time = time.time()
pythoncom.CoInitialize()
try:
self.word = win32com.client.DispatchEx("Word.Application")
logger.debug(f"Word application started in {time.time() - start_time:.2f} seconds")
except Exception as ex:
logger.error("Error starting Word application", exc_info=ex)
raise
return self
def __exit__(self, exc_type, exc_val, exc_tb):
logger.debug("Closing Word application...")
try:
if self.word:
self.word.Quit()
pythoncom.CoUninitialize()
logger.debug("Word application closed")
except Exception as ex:
logger.error("Error closing Word application", exc_info=ex)
raise
def process_document(self, docx_file):
"""Handles both TOC update and PDF conversion in a single Word session"""
logger.debug(f"Opening document: {docx_file}")
start_time = time.time()
if not os.path.exists(docx_file):
logger.error(f"The file does not exist: {docx_file}")
raise Exception(f"The file does not exist: {docx_file}")
try:
# Log Word application state
logger.debug(f"Word application object exists: {self.word is not None}")
doc = self.word.Documents.Open(docx_file)
# Check if document was opened successfully
if doc is None:
logger.error("Failed to open document - Word returned None")
raise Exception("Failed to open document in Word")
logger.debug(f"Document opened in {time.time() - start_time:.2f} seconds")
logger.debug(f"Document object exists: {doc is not None}")
# Add diagnostics for the document
try:
logger.info(f"Document name: {doc.Name}")
logger.info(f"Document path: {doc.Path}")
logger.info(f"Document pages: {doc.ComputeStatistics(2)}") # 2 is for page count
logger.info(f"Document paragraphs count: {len(doc.Paragraphs)}")
except Exception as doc_ex:
logger.error(f"Error accessing document properties: {str(doc_ex)}")
raise Exception("Failed to access document properties")
# Check for Table of Contents
try:
toc_count = doc.TablesOfContents.Count
logger.info(f"Number of Tables of Contents found: {toc_count}")
except Exception as toc_ex:
logger.error(f"Error checking TOC count: {str(toc_ex)}")
toc_count = 0
# Only try to update TOC if it exists
if toc_count > 0:
logger.debug("Updating Table of Contents...")
toc_start = time.time()
doc.TablesOfContents(1).Update()
logger.debug(f"TOC updated in {time.time() - toc_start:.2f} seconds")
doc.Save()
else:
logger.warning("No Table of Contents found in document - skipping TOC update")
# Convert to PDF
pdf_file = docx_file.replace('.docx', '.pdf')
logger.debug(f"Converting to PDF: {pdf_file}")
pdf_start = time.time()
doc.SaveAs(pdf_file, FileFormat=17)
logger.debug(f"PDF conversion completed in {time.time() - pdf_start:.2f} seconds")
doc.Close()
logger.debug("Document closed")
return pdf_file
except Exception as ex:
logger.error(f"Failed to process document. Exception: {str(ex)}", exc_info=True)
if 'doc' in locals() and doc:
try:
doc.Close(SaveChanges=False)
logger.debug("Document closed after error")
except:
pass
raise Exception("Failed to process document. Check the file and try again.")
@app.route('/status', methods=['GET'])
def status():
return {'status': 'API is running', 'version': '1.0'}, 200
@app.route('/convert', methods=['POST'])
def convert():
logger.debug("Received conversion request")
if 'file' not in request.files:
logger.warning("No file provided in request")
return 'No file provided', 400
file = request.files['file']
if not file.filename.endswith('.docx'):
logger.warning(f"Invalid file format: {file.filename}")
return 'Invalid file format. Please upload a .docx file', 400
temp_dir = None
temp_docx = None
pdf_path = None
try:
logger.debug("Creating temporary directory...")
temp_dir = tempfile.mkdtemp()
temp_docx = os.path.join(temp_dir, 'input.docx')
logger.debug(f"Saving uploaded file to {temp_docx}")
file.save(temp_docx)
# Add file checks and logging
logger.info(f"File exists: {os.path.exists(temp_docx)}")
logger.info(f"Absolute file path: {os.path.abspath(temp_docx)}")
# Check file permissions
file_stat = os.stat(temp_docx)
permissions = stat.filemode(file_stat.st_mode)
logger.info(f"File permissions: {permissions}")
# Get current user
current_user = getpass.getuser()
logger.info(f"Current user: {current_user}")
logger.debug("Starting document processing...")
process_start = time.time()
with WordHandler() as word_handler:
pdf_path = word_handler.process_document(temp_docx)
logger.debug(f"Document processing completed in {time.time() - process_start:.2f} seconds")
response = send_file(
pdf_path,
mimetype='application/pdf',
as_attachment=True,
download_name='converted.pdf'
)
@response.call_on_close
def cleanup():
logger.debug("Starting cleanup...")
try:
if temp_docx and os.path.exists(temp_docx):
os.unlink(temp_docx)
if temp_dir and os.path.exists(temp_dir):
os.rmdir(temp_dir)
if pdf_path and os.path.exists(pdf_path):
os.unlink(pdf_path)
logger.debug("Cleanup completed")
except Exception as e:
logger.error(f"Error during cleanup", exc_info=e)
return response
except Exception as e:
logger.error("Error during conversion request", exc_info=e)
return str(e), 500
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5001, debug=True)
And here are the logs :
WARNING:werkzeug: * Debugger is active!
INFO:werkzeug: * Debugger PIN: 366-636-785
DEBUG:__main__:Received conversion request
DEBUG:__main__:Creating temporary directory...
DEBUG:__main__:Saving uploaded file to C:\Users\User\AppData\Local\Temp\tmp5dwqrhb1\input.docx
INFO:__main__:File exists: True
INFO:__main__:Absolute file path: C:\Users\User\AppData\Local\Temp\tmp5dwqrhb1\input.docx
INFO:__main__:File permissions: -rw-rw-rw-
INFO:__main__:Current user: User
DEBUG:__main__:Starting document processing...
DEBUG:__main__:WordHandler initialized
DEBUG:__main__:Starting Word application...
DEBUG:__main__:Word application started in 0.35 seconds
DEBUG:__main__:Opening document: C:\Users\User\AppData\Local\Temp\tmp5dwqrhb1\input.docx
DEBUG:__main__:Word application object exists: True
ERROR:__main__:Failed to open document - Word returned None
ERROR:__main__:Failed to process document. Exception: Failed to open document in Word
Traceback (most recent call last):
File "C:\Users\User\Desktop\docx2pdf\app.py", line 64, in process_document
raise Exception("Failed to open document in Word")
Exception: Failed to open document in Word
DEBUG:__main__:Closing Word application...
DEBUG:__main__:Word application closed
ERROR:__main__:Error during conversion request
Traceback (most recent call last):
File "C:\Users\User\Desktop\docx2pdf\app.py", line 64, in process_document
raise Exception("Failed to open document in Word")
Exception: Failed to open document in Word
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\User\Desktop\docx2pdf\app.py", line 160, in convert
pdf_path = word_handler.process_document(temp_docx)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\User\Desktop\docx2pdf\app.py", line 115, in process_document
raise Exception("Failed to process document. Check the file and try again.")
Exception: Failed to process document. Check the file and try again.
INFO:werkzeug:172.16.120.156 - - [09/Jan/2025 12:51:05] "[35m[1mPOST /convert HTTP/1.1[0m" 500 -
Thanks in advance.
本文标签:
版权声明:本文标题:windows - Python flask API to convert DOCX to PDF - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736662580a1946491.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论