Переход от пула экземпляров Excel к динамическому созданию экземпляровPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Переход от пула экземпляров Excel к динамическому созданию экземпляров

Сообщение Anonymous »

У меня есть API Flask на сервере Windows, который используется для создания/чтения/записи и запуска макроса в файлах Excel. Я использую xlwings для взаимодействия с Excel. /> Теперь я хотел бы динамически создавать экземпляры, когда пользователь нуждается в нем. Поскольку я не могу создать его непосредственно в потоке запроса (Excel не поддерживает неэтерикцию множественного потока с помощью экземпляра Excel), я подумал о запуске экземпляра так же, как я убиваю/запускаю новый экземпляр ATM (создайте данные Redis, которые сигнализируют в основной поток, который мне нужен новый экземпляр, а затем хранить PID экземпляра в Redis, и я не могу выполнить его, а я не могу выполнить его, а не будет выполнять его, а не в следующем, что не будет. Откройте рабочую книгу: < /p>

Код: Выделить всё

info:app found f

ERROR:custom_logger:Error opening workbook: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', 'La méthode Open de la classe Workbooks a échoué.', 'xlmain11.chm', 0, -2146827284), None)
< /code>
Вот код при использовании пула экземпляра: < /p>
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(SCRIPT_DIR))

# Initialize Flask app
app = Flask(__name__)

# Configure Flask logging
app.logger.setLevel(logging.DEBUG)

BUCKET_NAME = os.getenv('AWS_BUCKET')

# Initialize COM once during app startup, it's necessary for the communication between xlwings and excel
pythoncom.CoInitialize()

def create_excel_instances(number_of_instances):
xl_apps = []
number_of_instances = int(number_of_instances)
for i in range(1, number_of_instances + 1):
xl_app = xw.App(visible=False)
xl_app.screen_updating = False
xl_app.display_alerts = False
xl_app.enable_events = False
xl_app.ask_to_update_links = False
xl_app.ignore_remote_requests = True
redis_instance.set(f'XL_APP{i}_PID', xl_app.pid)
print(f'xl_app{i} pid: {xl_app.pid}')
xl_apps.append(xl_app)

backup_app = xw.App(visible=False)
backup_app.screen_updating = False
backup_app.display_alerts = False
backup_app.enable_events = False
backup_app.ask_to_update_links = False
backup_app.ignore_remote_requests = True
redis_instance.set('XL_APP_BACK_UP_PID', backup_app.pid)
print(f'backup app pid: {backup_app.pid}')
xl_apps.append(backup_app)
return xl_apps

# Create Excel instances
xl_apps = create_excel_instances(os.getenv('NUMBER_OF_EXCEL_INSTANCES'))

setup_routes(app)

# Start (or restart) scheduler
if scheduler.running:
scheduler.shutdown(wait=False)
scheduler.start()

def create_app():
return app

def restart_excel_instance(instance_key):
try:
custom_logger.info(f"Starting restart of instance {instance_key}")
old_pid = int(redis_instance.get(instance_key))
custom_logger.info(f"Old PID: {old_pid}")

try:
if old_pid in xw.apps:
custom_logger.info(f"Closing via xlwings Excel instance (PID: {old_pid})")
for book in xw.apps[old_pid].books:
try:
book.close()
except Exception as e:
custom_logger.error(f"Error closing workbook: {e}")
try:
xw.apps[old_pid].quit()
except Exception as e:
custom_logger.error(f"Error closing via xlwings: {e}")
except Exception as e:
custom_logger.error(f"Error during xlwings closure: {e}")
# Wait a bit to ensure the application is properly closed
time.sleep(2)

# Force closure via psutil if process still exists
try:
import psutil
process = psutil.Process(old_pid)
if process.is_running():
custom_logger.warning(f"Excel instance still running, attempting forced termination")
process.terminate()
process.wait(timeout=5)
custom_logger.info("Excel instance successfully terminated")
except psutil.NoSuchProcess:
custom_logger.info(f"Process {old_pid} no longer exists")
except Exception as e:
custom_logger.error(f"Error during forced process termination: {e}")

custom_logger.info("Creating new Excel instance")
xl_app = xw.App(visible=False)
xl_app.screen_updating = False
xl_app.display_alerts = False
new_pid = xl_app.pid
redis_instance.set(instance_key, new_pid)
custom_logger.info(f"New instance successfully created (PID: {new_pid})")

return True
except Exception as e:
custom_logger.error(f"Error during instance restart {instance_key}:  {e}")
return False

def check_for_restart_requests():
while True:
for instance_key in [f'XL_APP{i}_PID' for i in range(1, int(os.getenv('NUMBER_OF_EXCEL_INSTANCES')) + 1)] + ['XL_APP_BACK_UP_PID']:
restart_flag = redis_instance.get(f'{instance_key}_needs_restart')
if restart_flag and restart_flag.decode('utf-8') == '1':
print(f"Restart required for instance {instance_key}")
restart_excel_instance(instance_key)
redis_instance.delete(f'{instance_key}_needs_restart')
time.sleep(5)

restart_checker = threading.Thread(target=check_for_restart_requests, daemon=True)
restart_checker.start()

if __name__ == "__main__":
from waitress import serve
serve(app, host="0.0.0.0", port=5000, threads=int(os.getenv('MAX_THREADS', 4)))
< /code>
И вот тот, когда я пытаюсь создать динамические экземпляры: < /p>
CRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(SCRIPT_DIR))

# Initialize Flask app
app = Flask(__name__)

# Configure Flask logging
app.logger.setLevel(logging.DEBUG)

BUCKET_NAME = os.getenv('AWS_BUCKET')

# Initialize COM once during app startup, it's necessary for the communication between xlwings and excel
pythoncom.CoInitialize()

def setup_xl_app():
print('open first app')
first_xl_app = xw.App(visible=False)
first_xl_app.screen_updating = False
first_xl_app.display_alerts = False

redis_instance.set('first_xl_instance', first_xl_app.pid)
print('open done')
return [first_xl_app]

xl_apps = setup_xl_app()

setup_routes(app)

# Start (or restart) scheduler
if scheduler.running:
scheduler.shutdown(wait=False)
scheduler.start()

def create_app():
return app

def open_excel_instance(user_id):
custom_logger.info("Creating new Excel instance")
try:
xl_app = xw.App(visible=False)
xl_app.screen_updating = False
xl_app.display_alerts = False

new_pid = xl_app.pid
instance_key = f'xl_instance_user_{user_id}'
redis_instance.set(instance_key, new_pid)

try:
_ = xl_app.calculation
custom_logger.info(f"New instance successfully created (PID: {new_pid})")
return True
except Exception as e:
custom_logger.error(f"Instance créée mais test échoué: {e}")
try:
xl_app.quit()
except:
pass
redis_instance.delete(instance_key)
return False

except Exception as e:
custom_logger.error(f"Error creating Excel instance: {e}")
return False

def check_for_restart_requests():
while True:
user_id = redis_instance.lpop('start_xl_instance')
if user_id:
user_id = user_id.decode('utf-8')
open_excel_instance(user_id)
else:
time.sleep(2)

restart_checker = threading.Thread(target=check_for_restart_requests, daemon=True)
restart_checker.start()

if __name__ == "__main__":
from waitress import serve
serve(app, host="0.0.0.0", port=5000, threads=int(os.getenv('MAX_THREADS', 4)))
Я не вижу разницы между двумя способами создания экземпляров, есть ли у вас есть представление о том, почему я могу использовать экземпляр в первую очередь, но нет во втором пути?

Подробнее здесь: https://stackoverflow.com/questions/796 ... -instances
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Каковы некоторые распространенные подходы к динамическому созданию пользовательского интерфейса в Angular для специфичны
    Anonymous » » в форуме C#
    0 Ответы
    6 Просмотры
    Последнее сообщение Anonymous
  • Руководство по созданию классов и экземпляров Enum в Python
    Гость » » в форуме Python
    0 Ответы
    6 Просмотры
    Последнее сообщение Гость
  • Руководство по созданию классов и экземпляров Enum в Python
    Гость » » в форуме Python
    0 Ответы
    4 Просмотры
    Последнее сообщение Гость
  • ASP.NET WEB API не привязывается к динамическому объекту в POST
    Гость » » в форуме C#
    0 Ответы
    36 Просмотры
    Последнее сообщение Гость
  • ASP.NET WEB API не привязывается к динамическому объекту в POST
    Гость » » в форуме C#
    0 Ответы
    20 Просмотры
    Последнее сообщение Гость

Вернуться в «Python»