Подпроцесс Python: откройте программу и подождите, пока пользователь сохранит и закроет ее

#python-3.x #subprocess

#python-3.x #подпроцесс

Вопрос:

У меня есть код, который запускает файл Excel в графическом интерфейсе. Затем он обновляется пользователем и закрывается. Этот пользовательский ввод позже используется программой. Поэтому я хочу, чтобы моя программа ждала, пока пользователь не закроет файл Excel в графическом интерфейсе. Я попытался следовать, но, я думаю, он только ждет открытия программы.

 import subprocess
loc = "C:\Users\Public\Documents\Sheet_groups.xlsx"
p = subprocess.Popen(['start',loc],stdout=subprocess.PIPE,shell = True)
p.communicate()
  

PS: я новичок в мире программирования

Ответ №1:

Вы можете использовать psutil (процессные и системные утилиты), чтобы проверить, открыт ли процесс Excel. Попробуйте это :

 import psutil
import subprocess
import time
isopen=True

loc = "C:\Users\Public\Documents\Sheet_groups.xlsx"
p = subprocess.Popen(['start',loc],stdout=subprocess.PIPE,shell = True)
time.sleep(2)
while(isopen):
    isopen="EXCEL.EXE" in (p.name() for p in psutil.process_iter()) 
    time.sleep(2)

print("File closed")
  

Чтобы проверить, открыта ли конкретная windows, вы можете использовать библиотеку pywinauto, установив ее с помощью.

pip install pywinauto

Затем попробуйте :

 import subprocess
import time
from pywinauto import Desktop

isopen=True
loc = "C:\Users\Public\Documents\Sheet_groups.xlsx"
p = subprocess.Popen(['start',loc],shell = True)
time.sleep(2)

windows = Desktop(backend="uia").windows()

while(isopen):
    isopen="Sheet_groups.xlsx - Excel" in [w.window_text() for w in windows]
    time.sleep(2)
    
print("File closed")
  

Вы можете попробовать это, если не можете использовать pywinauto:

 import subprocess
import time
import win32gui

isopen=True
loc = "C:\Users\Public\Documents\Sheet_groups.xlsx"
running=""

def winEnumHandler( hwnd, ctx ):
    global running
    if win32gui.IsWindowVisible( hwnd ):
        running =win32gui.GetWindowText( hwnd )
    
    

p = subprocess.Popen(['start',loc],shell = True)
time.sleep(2)

while(isopen):
    isopen=win32gui.EnumWindows( winEnumHandler, None )
    isopen="Sheet_groups.xlsx" in running
    running=""
    time.sleep(2)
    
print("File closed")
  

Комментарии:

1. Спасибо за ответ. Я получаю psutil.AccessDenied: psutil.AccessDenied (pid=8) , вероятно, потому, что я нахожусь на рабочем ноутбуке без прав администратора. В любом случае, не думаете ли вы, что ваше решение скажется на ресурсах процессора, если пользователь решит оставить Excel открытым надолго? @Fadi

2. Да, вам нужны права администратора. Похоже, что он будет использовать много ресурсов процессора, если в цикле есть задержка, которая проверяет, открыт ли Excel. Итак, я исправил это, добавив задержку в 2 секунды.

3. Что делать, если у пользователя открыто несколько файлов Excel? Я думаю, в этом случае цикл останется открытым. Есть ли какой-нибудь чистый способ ожидания, например, с использованием потоков и очередей?

4. Да, цикл останется. Для решения этой проблемы вам понадобится другой подход.

5. Я добавил способ проверить, открыта ли определенная windows, но вам необходимо установить внешнюю библиотеку.